无法在写入上下文中使用方法返回值

475

我会认为下面这段代码应该可以工作,但实际上并没有(已编辑:现在在 PHP 5.5+ 中可以工作)

if (!empty($r->getError()))

其中getError()仅仅是:

public function getError()
{
    return $this->error;
}

然而我最终遇到了这个错误:

无法在写入上下文中使用方法返回值

这是什么意思?这不只是一个读取吗?


2
可能在PHP 5.5中,您将被允许将表达式传递给empty:https://wiki.php.net/rfc/empty_isset_exprs - Carlos Campderrós
2
PHP的isset和empty权威指南 - deceze
好的,我发现 porneL 的答案 也是正确的。我的代码是 if ( !$e->find('div') ),它检查当前的 HTML DOM 元素是否为空。我在循环内使用它来仅打印出不包含内部 Div 的单个 Div。 - Salem
8个回答

782

empty()需要通过引用来访问值(以检查该引用是否指向某个存在的东西),而PHP 5.5之前不支持对从函数返回的临时值的引用。

然而,你真正面临的问题是你在使用empty(),错误地认为"空"值与"false"有所不同。

空只是!isset($thing) || !$thing的别名。当你要检查的东西始终存在时(在PHP中,函数调用的结果始终存在),empty()函数就是一个否定运算符。

PHP没有空的概念。评估为false的值是空的,评估为true的值是非空的。这段代码:

$x = something();
if (empty($x)) …

以及这个:

$x = something();
if (!$x) …

无论数据类型如何,对于所有情况empty()函数始终具有相同的结果(因为变量$x已经被定义为空)。

该方法始终返回一个值(即使没有return语句,返回值仍然存在且包含null)。因此:

if (!empty($r->getError()))

逻辑上等同于:

if ($r->getError())

30
这个回答比目前被选择的更好。 - SystemParadox
20
@gcb:不是的,PHP手册明确表示它们是相同的:“empty()(boolean) var 的反义词,唯一的区别是当变量未设置时不会生成警告。” - Kornel
17
不生成警告信息的部分非常重要......empty($var)将在以下情况下返回true:0、''、array()、NULL或甚至未定义。这是良好的编程实践,特别是可以记录您真正的警告信息,而不是让文件填满警告信息。 - landons
3
好的,很棒的回答,但是避免这种情况的正确方法是什么?有人知道吗? - Javatar
3
一般来说没问题,但它并不严格等同于empty(),因为“”、“0”等是“空的”,但不是null。 - Kornel
显示剩余9条评论

331
请注意:这是一个非常受欢迎且非常可见的答案,但请注意它促进了不好的、不必要的编码实践!请参阅@Kornel's answer以了解正确的方法。
注意事项2:我支持使用@Kornel's answer的建议。当我三年前写下这个答案时,我只是想解释错误的本质,并不一定支持替代方案。下面的代码片段不推荐使用。
这是 PHP 版本低于 5.5 的一个限制。
注意:empty() 只能检查变量,其他任何内容都会导致解析错误。换句话说,以下代码是无效的:empty(trim($name))。
你需要改成这样。
// Not recommended, just illustrates the issue
$err = $r->getError();
if (!empty($err))

156
这样做非常没有效果。 - David Murdoch
47
注意:isset() 也是同样的情况。例如:isset($this->foo->getBar()) 将会导致同样的问题。 - catchdave
7
Pornel的回答详细解释了这一点,并提供了更好的解决方案。 - SystemParadox
5
取决于你对“更好”的定义。porneL的答案可能更全面并提供了一个“更简洁”的解决方案,但也没有解释错误的来源。 - Peter Bailey
4
因为它并没有错,@deceze。这不是最好的答案,我不会反驳这一点。我甚至投了poreL的赞同票。虽然这是一个非常老的回答,但它并没有错误。至于高票:请记住,poreL的回答几乎晚了整整17个月才到来。 - Peter Bailey
显示剩余3条评论

38
在 PHP 5.5 之前,PHP 文档 中曾经写道:

empty() 只能检查变量,否则会导致语法解析错误。

在 PHP < 5.5 上,你不能直接在函数的返回值上使用 empty()。相反,你需要将 getError() 的返回值赋给一个变量,并在变量上运行 empty()

在 PHP >= 5.5 中,这已经不再需要了。


19

我通常会创建一个名为is_empty()的全局函数来解决这个问题。

function is_empty($var)
{ 
 return empty($var);
}

那么在我通常使用 empty() 的任何地方,我只需使用 is_empty()。


2
最好不要这样做,而是坚持标准(尽管它们可能很烦人)。 - tonyhb
1
@dynamism 你能解释一下为什么不行吗? - Janis Veinbergs
1
因为便利函数在别人的代码中阅读起来可能很麻烦。此外,在MVC/HMVC架构中,它可能会破坏你的结构。归根结底,PHP程序员应该知道它的限制,并能够理解没有便利函数的小型解决方案。 - tonyhb
14
哇,你刚刚发明了一个“否定函数”。你知道PHP有!运算符可以实现这个功能吗? :) - Kornel

4

正如其他人指出的那样,这是empty()函数的一个(奇怪的)限制。

对于大多数情况而言,这么做等同于调用empty()函数,但是以下方法也可以达到同样的效果:

if ($r->getError() != '')

5
这不是真的——"empty()"覆盖了比空字符串更多的可能性。 - scrowler
3
这就是为什么它说“适用于大多数情况”,而不是所有情况 - Jani Hartikainen

2
问题在于,您想知道错误是否为空。
public function getError() {
    return $this->error;
}

添加一个isErrorSet()方法就可以解决这个问题。
public function isErrorSet() {
    if (isset($this->error) && !empty($this->error)) {
        return true;
    } else {
        return false;
    }
}

现在,这段代码可以正常运行,没有任何提示。

if (!($x->isErrorSet())) {
    echo $x->getError();
}

1

我不确定这是否是一个常见的错误,但如果您做了类似以下的事情:

$var = 'value' .= 'value2';

这也会产生相同的错误。

无法在写入上下文中使用方法返回值

你不能在同一语句中同时使用=.=。你可以使用一个或另一个,但不能同时使用。

请注意,我明白这与问题中实际的代码无关,但当搜索错误消息时,此问题是顶部结果,因此我想在这里发布以保持完整性。


-3

检查数组是否为空的另一种方法可能是:

count($array)>0

对我来说,它可以正常工作,没有出现错误。


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