更多的是评论而不是答案 - 但对于评论框来说太长了。还有一个引人入胜的问题,让我问“为什么”。
直接回答:
- 不声明变量不会在任一版本中导致“通知” - 因此从技术上讲,它不是必需的。
- 因此,声明是一种优先事项。像Alex 一样,我更喜欢声明可读性和清晰性。 (我也更喜欢避免使用像
extract 这样的函数,它们会从无处创建变量。)但我相信其他人会不同意。
但这导致了为什么它会这样工作的问题?我很想知道。
首先要注意的是,通过引用传递的变量和变量从 PHP 5 到 PHP 7 发生了很大变化。这里有一篇有趣的文章:https://nikic.github.io/2015/05/05/Internal-value-representation-in-PHP-7-part-1.html 解释了这些差异。
但是在这两种 PHP 中,变量都存储在 zval 空间中,并带有一个引用计数器,用于计算变量被引用的次数。 (上面的那个文档是我在解释它时找到的最好的例子,但manual 中还有更多)
当您扩展 PHP 并添加新函数时,您可以使用 zend_parse_parameters 从 Zend API 获取变量。这意味着传递给函数的变量也存储在 zval 容器中,并在 API 和扩展之间传递。 (Further reading - 这与 PHP5 有关,但与 PHP7 相同)。
四个代码示例解释了我的理解(我很高兴得到纠正):
1)
function increment($i) {
$i++;
}
increment(3);
变量3 没有声明(很明显),但它需要在zval 容器中才能传递给API。这表明调用函数能够在 zval 容器中生成变量。 (因为它不是一个真正的变量,我认为它是“不可变的”,但这是一个猜测。)
2)
function increment($i) {
$i++;
}
increment($y);
此错误为 $y 未首先声明。 Notice: Undefined variable: y in test.php。所以在这里它无法生成$y 并放入本地范围。
3)
function increment($i) {
$i++;
}
$y = 0;
increment($y);
变量被声明并放入 zval 容器中。调用函数时,会增加 refcount,以便将其传递给 API。按预期工作。
4)
function increment(&$i) {
$i++;
}
increment(3);
此错误Fatal error: Only variables can be passed by reference in test.php。这告诉我们变量3 被zend_parse_parameters 拒绝,因为它知道它是不可变的,或者调用函数知道该函数需要一个引用变量。
5)
function increment(&$i) {
$i++;
}
$y = 0;
increment($y);
变量$y第一行放入当前作用域的zval容器中,生成$y的引用指针(增加两次refcount)。
6)
function increment(&$i) {
$i++;
}
increment($y);
这是梨形 IMO 的去处:虽然没有声明变量,但 $y == 1。这意味着该函数必须在当前范围内创建变量并放入zval容器中,并生成指向$y的引用指针(增加refcount)。
要做到这一点,它必须知道该函数通过引用期待一个值 - 否则为什么行为与 2 不同?
这些都不能解释为什么它不同。正因为它可以创建一个变量(如示例1所示),为什么示例2中没有,而示例6中却可以?