在过去的几个星期里,三元运算符和null合并了很多,并且非常喜欢它能够简化我的逻辑的方式,特别是在以前我必须堆叠一系列if (!empty($variable))的地方 - 一系列已经烦人的大if/else语句的行。现在我可以$object->attribute = $source->attribute ?? null,假设我不知道source中是否有属性。
现在,我遇到问题的问题是试图弄清楚如何最好地使用它进行日志记录。说我有一个像以下的功能:
public static function addToQueue($field, $id)
{
if ($field ?? $id ?? null == null) {
return false;
} elseif ($field != 'name' && $field != 'id') {
return false;
} elseif (Queue::where($field, $id)->count() != 0) {
return true;
} else {
Queue::insert([$field => $id]);
return true;
}
}
非常坦率的;你发送addToQueue()两个参数,field和id,然后进行三次检查。他们中的任何一个null?然后返回false。 field name或id以外的其他内容?然后返回false。此条目是否已在队列中?然后返回true(因为我们有兴趣确保条目在队列中,而不是我们现在是否添加它)。最后,如果该对不在队列中,我们将其添加 - 再次 - 返回true。
现在;到现在为止还挺好;对?这似乎不是一个问题,即使我看到我怎么可能使函数内部的逻辑更整洁。问题在于我使用它。基本上,我想要做的是这样的 - 但使用三元运算符:
if (QueueHandler::addToQueue($input->field, $input->value) == true) { $app->log->info($input->field . '/' . $input->value . ' added to queue.'; }
我希望它执行某些操作,如果它执行的操作评估为true,但如果它的计算结果为false则不执行任何操作。
是的,我知道,它叫做Ternary,因为你需要三个操作,但是现在PHP允许你isset($variable) ?: echo 'Dude. It\'s not set...';,我认为应该有办法做相反的事,对吧?
不要强行使用ternarys。 Ternarys应该几乎专门用于分配或返回两个值,而不是执行副作用。 如果您在特定情况下使用它们有困难,那很可能表明它们的使用不合适。
没有多看(因为我刚刚醒来); 乍一看,"null == null"可以替换为"true"。 但正如Carcig(更多信件)所说,为了简洁而丧失工作效率会产生相反的效果。
仅供参考:stackoverflow.com/questions/34571330/
$ id ?? null是没有意义的。 $id将始终在功能范围中设置。
??运算符是右关联的(源)
它的意思是:
$field??$id??null == null
如果$field未设置或为null,则折叠为:
$id??null==null
如果未设置$id,则归零为:
null==null
该表达式将始终为true,因为??运算符吞下了null。这意味着$field??$id??null==null永远不会评估为假值。
如果要强制优先,则需要明确:
($field??$id??null) == null
想玩ternarys?
喜欢它:
function addToQueue($field, $id)
{
return ($field??$id??null) == null?false:($field != 'name' && $field != 'id')?false:
(Queue::where($field, $id)->count() != 0)?true:Queue::insert([$field => $id])?true:true;
}
没有人会理解,甚至不是你。每次你必须改变它你会问自己为什么这样做,但它会让你的phpunit代码覆盖更容易。
现在认真,apokryfos发现了它。但是你必须问问自己,你在使用ternarys时会得到什么。
这对于以下事情非常有用:
function getClub(){
return $this->isClubVisible()? $this->club: null;
}
你用if / else解决的每一个操作,但是你可以看到如果你过度使用它,它将变得非常混乱和不可读。
所以,你当前的代码很简单
if (QueueHandler::addToQueue($input->field, $input->value) == true) {
$app->log->info($input->field . '/' . $input->value . ' added to queue.';
}
当addToQueue返回bool时,您可以简化为:
if (QueueHandler::addToQueue($input->field, $input->value)) {
$app->log->info($input->field . '/' . $input->value . ' added to queue.';
}
现在你要尝试使用它:
!QueueHandler::addToQueue($input->field, $input->value) ?: $app->log->info($input->field . '/' . $input->value . ' added to queue.';
我不认为它比以前的例子更具可读性。
三元是IF ELSE的简写。
即使您提到的代码isset($variable) ?: echo 'Dude. It\'s not set...';正在这样做(如果isset为true,它将返回$ variable),即使看起来你刚刚添加了else部分。所以没有"对立面"只有IF和ELSE
例如:
$a = 'foo';
echo $a ?: 'bar'; // 'foo'