PHP奇怪的语法 - 它被称为什么?

5

我一直在关注一个有关PHP框架的视频系列,遇到了一个奇怪的结构。我想知道它叫什么,这样我就可以进一步学习。在视频中,发言人提供了以下代码:

public function edit($id = NULL)
{
   $id == NULL || $this->data['user'] = $this->user_m->get($id);
   ...
}

他说,如果呼叫者未传递 ID,则 $id 将被设置为 null,如果传递了 $id,则将从数据库中检索用户并保存在数据数组中。
问题是,这是一个条件语句,但它不在 if 或 while 等语句中。我以前从未见过这样的情况。我搜索了内联或、条件语句外部的循环/if 语句、奇怪的语法等,但没有成功。正如我所说,我想更多地了解它,查找它是否是一般的 PHP 功能或特定于框架的。
谢谢。

2
那是一个三元操作符。 没有更多也没有遗漏,右侧的表达式虽然不太流行,但我个人不喜欢它。 据我所知,它与以下完全相同: $id!== NULL && $this->data ['user'] = $this->user_m->get($id); 或者更易读:$this->data['user'] = $id == NULL ? $this->user_m->get($id) : $this->data['user']; 简而言之,它基本上是说“如果id不为null(或者更精确地说,如果$id == null为falsey),则将$this->data ['user']设置为$this->user_m->get($id),否则只保持$id为null并继续进行”。 - briosheje
@b0s3:不,只是猜测而已,我已经习惯了这些,唯一让我困扰的是传递给函数的参数,我假设它应该是 $id = null 而不是 id == null,否则它甚至不应该编译通过,对吧? - briosheje
2
发布的源代码中没有使用三元运算符... - Sebastian P.
2
不,目前没有三元运算符参与... OR 明显是一个二元运算符。 - Sebastian P.
1
@briosheje:一元运算符是单个参数,二元运算符是两个参数,三元运算符是三个参数... 我的陈述中没有任何矛盾之处。 - Sebastian P.
显示剩余6条评论
2个回答

6
该语法称为“短路求值”,是大多数编程语言中使用的优化技术。当左表达式为假时,|| 的右表达式只有在需要计算结果时才会被计算,因为 -否则- 结果不依赖于右表达式的值(就像 && 的右表达式只有在左表达式为真时才会被计算)。
您可以将示例重写为($id == NULL) || ($this->data['user'] = $this->user_m->get($id));,以使其更清晰。只有当$id 不是 NULL 时,赋值表达式才会被计算。
但是,这行代码是难以维护的典型示例,因为你需要花费太多的时间思考它是如何运作的... :)

那么,这实际上几乎就像三元运算符的速记?我同意你对它难以维护的看法。我能理解它的作用,只是不知道可以用这种方式实现。 - Sethmo011

1
为了回答这个问题,我们必须先说一下,你的函数语法可能存在错误(我会说“可能”,因为我还不能100%确定)。
public function edit($id == NULL)

应该是:

public function edit($id = NULL)

这段代码的意思是,如果本地变量ID没有被设置,它会将其设置为NULL,否则就设置它的值。这样做与代码的其余部分完全相符。

话虽如此,正如评论中所说,剩下的部分只是一个OR逻辑操作(好吧,你可以以任何方式看待它,我习惯将其解释为三元运算符,因为如果有人不知道它是如何工作的,这样做会稍微容易一些),我只是觉得应该指出,与许多其他语言不同,在PHP中,您可以直接在逻辑操作的第二个、第三个或任何参数中评估变量。

简而言之,您的操作:

$id == NULL || $this->data['user'] = $this->user_m->get($id);

也可以写成:

if ($id !== null) {
   $this->data['user'] = $this->user_m->get($id);
}

当然,这是可读的,否则您也可以这样做:
$id !== NULL && $this->data['user'] = $this->user_m->get($id);

或者甚至:

$this->data['user'] = $id !== NULL ? $this->user_m->get($id) : $this->data['user'];

基本的三元运算符是:

condition ? iftrue : iffalse

你所说的“变化”实际上是一种逻辑操作的“使用”,称为短路求值。事实上,OR逻辑运算符仅在左侧运算符为假值时才评估右侧运算符。因此:
$id == NULL || $this->data['user'] = $this->user_m->get($id);

$id == NULL <-- 左操作数

$this->data['user'] = $this->user_m->get($id) <-- 右操作数

根据上面所说,如果 $id == NULL 是假值(也就是说,如果 $id 不为 null),那么执行右操作数,将 $this->data['user'] 设为 $this->user_m->get($id),否则不执行任何操作。


1
这不是三元运算符,而是布尔“或”运算符。 - BlitZ
我提供了很多关于同一件事的解释,但好吧,我们说这只是一个布尔或,让我们看看是否更清楚地说它是一个布尔或者只是某种可以被解释为类似简写的东西。我认为最好指出 $id==NULL 作为参数将永远不会编译通过,而不是那个。 - briosheje
当然,您可以重写代码以表达其他意思... 但是,这会改变问题的语义。我回答的是问题中原始代码的语义,其中没有涉及任何三元运算符。 - Sebastian P.
谢谢你的回答。是的,我的函数参数错了。我理解了它的含义,一开始看到它时,我也认为它类似于三元运算符,但语法与我之前遇到的完全不同,所以我想知道它是否真的是三元运算符,还是完全不同的东西。现在我知道了,我已经更深入地了解了它。我相信,在使用三元运算符或if语句的时候,有时候会用到它。 - Sethmo011
@Sethmo011:这在很大程度上取决于您的编码风格和个人偏好:我个人经常使用简写运算符,当您需要设置变量以避免意外错误时,OR逻辑运算符非常有用。在这种情况下,我个人认为一个更清晰的三元运算符比那个更好,但是如果您需要为$id设置默认值,例如,您可以轻松地执行以下操作:$id = $id || 1; <-- 如果$id为falsey(null为falsey),则将ID设置为1。简而言之,只要它们不变得过于复杂,这些代码就不难维护。 - briosheje
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接