在过去的几个星期里一直在玩三元运算符和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...';
,我认为应该有办法做相反的事情,对吧?
??
算子是右联合(Source)
它的意思是:
$field??$id??null == null
如果$field
未设置或为null,则折叠为:
$id??null==null
如果$id
未设置或null,则折叠为:
null==null
该表达式将始终为真,因为??
运算符吞下了null。这意味着$field??$id??null==null
永远不会评估为假值。
如果要强制优先,则需要明确:
($field??$id??null) == null
三元是IF ELSE的简写。
甚至你提到的代码isset($variable) ?: echo 'Dude. It\'s not set...';
正在这样做(如果isset为真,它将返回$ variable),即使看起来你刚刚添加了else部分。所以没有“对立面”只有IF和ELSE
例如:
$a = 'foo';
echo $a ?: 'bar'; // 'foo'
所以,你当前的代码很简单
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.';
我不认为它比以前的例子更具可读性。
想玩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解决的每一个操作,但是你可以看到如果你过度使用它,它将变得非常混乱和不可读。