根据大多数编程语言的范围规则,我可以访问在它们内部的函数之外定义的变量,但为什么这段代码不起作用?
<?php
$data = 'My data';
function menugen() {
echo "[" . $data . "]";
}
menugen();
?>
输出是[]
。
它不起作用,因为您必须声明要访问的全局变量:
$data = 'My data';
function menugen() {
global $data; // <-- Add this line
echo "[" . $data . "]";
}
menugen();
否则,您可以将其作为$GLOBALS['data']
. 请参阅变量范围。
即使有点离题,我建议您完全避免使用全局变量,而更喜欢作为参数传递。
您可以执行以下操作之一:
<?php
$data = 'My data';
function menugen() {
global $data;
echo "[" . $data . "]";
}
menugen();
或者
<?php
$data = 'My data';
function menugen() {
echo "[" . $GLOBALS['data'] . "]";
}
menugen();
话虽如此,过度使用全局变量会导致一些糟糕的代码。通常最好传递你需要的东西。例如,您应该将一个句柄传递给数据库并对其进行操作,而不是引用全局数据库对象。这称为依赖注入。当您实施自动化测试(您应该这样做)时,它会让您的生活变得更轻松。
另一种方法:
<?php
$data = 'My data';
$menugen = function() use ($data) {
echo "[".$data."]";
};
$menugen();
更新 2020-01-13:彼得莫滕森要求
从 PHP 5.3.0 开始,我们支持可以创建闭包的匿名函数。闭包可以访问在其范围之外创建的变量。
在示例中,闭包能够访问$data
,因为它是在use
子句中声明的。
这是范围的问题。简而言之,应该避免使用全局变量:
您要么需要将其作为参数传递:
$data = 'My data';
function menugen($data)
{
echo $data;
}
或者将它放在一个类中并访问它
class MyClass
{
private $data = "";
function menugen()
{
echo this->data;
}
}
另请参阅@MatteoTassinari 答案,因为您可以将其标记为全局以访问它,但通常不需要全局变量,因此重新考虑您的编码是明智的。
多年来,我一直使用这种格式:
<?php
$data = "Hello";
function sayHello(){
echo $GLOBALS["data"];
}
sayHello();
?>
我觉得它简单易懂。$GLOBALS 是 PHP 让您引用全局变量的方式。如果您使用过 $_SERVER、$_POST 等,那么您在不知情的情况下引用了一个全局变量。
<?php
$data = 'My data';
$menugen = function() use ($data) {
echo "[ $data ]";
};
$menugen();
?>
你也可以简化
echo "[" . $data . "]"
到
echo "[$data]"
由于这个原因,PHP 可能会令人沮丧。上面使用的答案global
对我不起作用,我花了一段时间才弄清楚use
.
这是对的:
$functionName = function($stuff) use ($globalVar) {
//do stuff
}
$output = $functionName($stuff);
$otherOutput = $functionName($otherStuff);
这是不正确的:
function functionName($stuff) use ($globalVar) {
//do stuff
}
$output = functionName($stuff);
$otherOutput = functionName($otherStuff);
使用您的具体示例:
$data = 'My data';
$menugen = function() use ($data) {
echo "[" . $data . "]";
}
$menugen();
您需要将变量传递给函数:
$data = 'My data';
function menugen($data)
{
echo $data;
}