为什么我会收到“只有变量应该按参考传递”错误提示?

9

看看这段代码:

$last = end($p = explode('/', $someString));  

收到以下通知:

仅应按引用传递变量

我很困惑,因为$p是一个变量。


您能展示更多的代码吗? $someString 是一个数组吗? - demonking
1
@demonking:为什么需要更多的代码? - Amal Murali
抱歉,我犯了个错误,请从你的代码中删除$p = - demonking
可能是仅应传递变量的引用的重复问题。 - miken32
4个回答

12

end()期望一个变量而不是一个引用。在你的例子中,$p = explode('/', $someString)不是一个变量,而是一个赋值语句。正如文档所说:

这个数组被按引用传递,因为它被函数修改。这意味着你必须传递一个真正的变量而不是返回一个数组的函数,因为只有实际的变量可以按引用传递。

相反,你应该这样做:

$p = explode('/', $someString);
$last = end($p); 

@ruakh 你说得对,这没有意义... 我会把它删除。谢谢。 - Tchoupi
我还是不明白。我特意将explode的返回值分配给一个变量,所以我不会看到那个提示,但我仍然看到它。 - thelolcat
1
@thelolcat 其实我也不明白其中的根本原因。如果你严格按照文档操作,$p = explode('/', $someString) 并不是一个变量。我正在研究为什么要将引用作为参数而不是变量本身。 - Tchoupi
@MathieuImbert 你是对的。它没有使用变量,因为 $p = explode('/', $someString) 是一个语句,它返回的不是引用,而是值本身。也就是说,$a = $b = 'x',意味着将 $b 的值返回给 $a,而不是 $b 的引用。在另一种情况下,OP正在询问的是,$a 将取决于 $b 的值(应用于 $b 的更改将影响 $a 的值),这是不明显的。默认情况下,它们应该是完全独立的,除非该值是一个对象,因为对象会隐式地通过引用传递。 - BlitZ
2
@MathieuImbert 无论如何,多重赋值都返回值而不是变量,因此PHP目前无法通过OP建议的方法创建引用。 - BlitZ
显示剩余3条评论

11

函数end()需要一个实数变量而不是返回数组的函数,但是如果你将函数返回值放在双括号中,PHP就不会报告严格标准通知:

函数end()需要一个实数变量而不是返回数组的函数,但如果您将函数返回值放在双括号中,PHP不会报告严格标准通知:

$last = end( ( explode( '/', $someString ) ) );

希望这不是一个错误。 - thelolcat
虽然我不建议抑制警告和通知,但这很有趣。它显然与你描述的完全一样,Danijel。这种行为在php手册中有记录吗?我找不到任何参考资料。 - Jiri
这里有一个关于这个话题的有趣讨论,但似乎没有人确定这种行为是特性还是错误。 - Danijel
2
@Jirka 这是有文档记录的,当你使用 $b = ($a = 5) 时,第二个部分不再是一个表达式,而是变成了一个变量。 - revo

5
问题在于您正在将一个值分配给一个函数,而传递给$last的值实际上是该函数的结果,而不是$p。另外,explode返回对变量的引用。
请分成两行完成操作:
$p = explode('/', $someString);
$last = end($p);  

在end()函数调用内部赋值给$p是没有必要的,除非你后面还要使用$p。为了代码风格的清晰明了,我建议分两步来做。


3

end() 这样的函数会影响变量并改变它们的值,如果它们应该,这意味着传递的是引用!但这种传递需要一定的倾向性,我们不能毫不在意地将东西推给它们!

当出现 Only variables should be passed by reference 时,实际上问题不在于变量,而是在于当你尝试使用 end($p = explode('/', $someString)); 时,将其传递给函数的方式,因为在调用 end() 时,你不被允许对其进行引用,你将一个表达式作为输入而不是一个变量。

表达式

PHP采用了更进一步的表达式,就像其他许多语言一样。PHP是一种面向表达式的语言,几乎所有东西都是表达式。考虑我们已经处理过的示例$a = 5。很容易看出这里涉及到两个值,即整数常量5的值和正在更新为5的$a的值。但事实上,在这里涉及到一个额外的值,那就是赋值本身的值。赋值本身会评估为分配的值,在这种情况下为5。实际上,这意味着$a = 5,无论它做什么,都是一个具有值5的表达式。因此,编写类似$b = ($a = 5)的内容就像编写$a = 5; $b = 5;(分号表示语句的结尾)。由于赋值按从右到左的顺序解析,您还可以编写$b = $a = 5。
那个错误只是您的情况下的严格错误,而不是致命错误!您知道PHP是一种严格的编程语言。但是您可以手动禁用它们。这并不改变结果。

这个问题的一些例子:

function foo($a)
{
    return ++$a;
};
$b = 1;
echo foo(&$b);

错误:

致命错误: 已删除按引用传递的调用时间; 如果您想通过引用传递参数,请修改foo()的声明自PHP 5.3.0起

或者

function foo(&$a)
{
    return ++$a;
};
echo foo($b = 1); // output: 2

我们之前见过这个错误 Strict Standards: Only variables should be passed by reference


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