function foo () {
global $var;
// rest of code
}
在我的小型PHP项目中,我通常采用过程化的方式。我通常有一个包含系统配置的变量,当我需要在函数中访问此变量时,我会使用global $var;
。这种做法是否不好?
function foo () {
global $var;
// rest of code
}
在我的小型PHP项目中,我通常采用过程化的方式。我通常有一个包含系统配置的变量,当我需要在函数中访问此变量时,我会使用global $var;
。当人们在其他语言中谈论全局变量时,它的含义与在PHP中稍有不同。这是因为在PHP中变量并不是真正的全局的。一个典型的PHP程序的作用域是一个HTTP请求。会话变量实际上比PHP中的“全局”变量具有更广泛的作用域,因为它们通常包含许多HTTP请求。
通常(总是?)您可以像这样在方法中调用成员函数preg_replace_callback()
:
preg_replace_callback('!pattern!', array($obj, 'method'), $str);
更多信息请参阅回调函数。
重点是对象已经被添加到了PHP中,并且在某些方面会导致一些尴尬。
不要过分关注将其他语言的标准或结构应用到PHP上。另一个常见的陷阱是通过在所有东西上堆叠对象模型来将PHP变成一个纯粹的OOP语言。
像任何其他东西一样,使用“全局”变量、过程式代码、特定框架和OOP是因为它有意义,解决了问题,减少了需要编写的代码量,或者使其更易于维护和理解,而不是因为您认为自己应该这样做。
preg_replace_callback()
时,你不能使用形式为 array($obj, 'callbackMethod')
的回调函数吗?(我知道,我已经陷入了这个面向对象编程的陷阱中...) - grossvogel全局变量如果不小心使用会使问题更难以找到。假设您请求一个PHP脚本,并收到警告,指出您正在尝试访问某个函数中不存在的数组索引。
如果您要访问的数组是函数内部的局部变量,您可以检查该函数,看看是否在那里犯了错误。这可能是函数输入有问题,因此您需要检查调用该函数的地方。
但如果该数组是全局的,则需要检查使用该全局变量的所有地方,而且不仅如此,还必须确定全局变量的参考顺序。
如果代码片段中有全局变量,则难以隔离该代码的功能。为什么要隔离功能?这样您就可以测试它并在其他地方重复使用。如果您有一些不需要测试且不需要重复使用的代码,则可以使用全局变量。
我同意被接受的答案。我想再添加两点:
使用前缀以便立即将其识别为全局变量(例如 $g_)
在一个位置中声明它们,不要在代码中随意分散它们。
$DB = 'foo';
。 - pixeline如果必须使用全局变量,请尝试在不使用它们的情况下解决问题。只有你真正理解问题的本质,而不仅仅是问题的描述,才能更好地处理冲突、测试和调试。
以下是从已结束的SO文档测试版中转载的
我们可以用下面的伪代码来说明这个问题
function foo() {
global $bob;
$bob->doSomething();
}
这里的第一个问题很显然:
$bob
是从哪里来的?
你感到困惑了吗?好的。你刚刚学会了全局变量为什么容易混淆且不被推荐使用。如果这是一个真实的程序,那么下一步有趣的事情就是去追踪所有 $bob
的实例并希望你找到了正确的(如果 $bob
在所有地方都被使用则会更糟)。更糟糕的是,如果其他人定义了 $bob
(或者你忘记了并重新使用了该变量),你的代码可能会出错(在上面的代码示例中,使用错误的对象或根本没有对象将导致致命错误)。由于几乎所有 PHP 程序都使用像 include('file.php');
这样的代码,因此随着添加更多文件,维护这样的代码的工作将呈指数级增长。
我们如何避免全局变量?
避免全局变量的最佳方法是一种称为依赖注入的理念。这是我们将需要的工具传递到函数或类中的方法。
function foo(\Bar $bob) {
$bob->doSomething();
}
这样做会更易于理解和维护。不需要猜测$bob
在哪里被设置,因为调用者有责任知道(它正在传递给我们所需的信息)。更好的是,我们可以使用类型声明来限制传递的内容。因此,我们知道$bob
是Bar
类的实例或Bar
子类的实例,这意味着我们知道我们可以使用该类的方法。结合标准的自动加载程序(自PHP 5.3以来可用),我们现在可以追踪Bar
的定义位置。PHP 7.0或更高版本包括了扩展的类型声明,您还可以使用标量类型(如int
或string
)。
$bob = Bar::instance();
即可。 - Scoots作为:
global $my_global;
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']
是一种不好的做法(例如 Wordpress 的 $pagenow
)... 嗯
考虑一下这个:
$my-global = 'Transport me between functions';
PHP错误 但是:
$GLOBALS['my-global'] = 'Transport me between functions';
这并不是错误,连字符不会与像$pagenow
这样的“普通”用户声明变量冲突。而使用大写字母表示正在使用的超全局变量,在代码中易于识别,或者可以通过文件中查找进行跟踪。
如果我懒得为单个解决方案构建所有类,我会使用连字符,例如:
$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';
但在更广泛的使用情况下,我使用一个全局数组:
$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';
对我来说,后者是关于“可乐轻”目标或用途的良好实践,而不是每次都使用单例类来“缓存”一些数据。如果我错了或漏掉了什么愚蠢的东西,请发表评论...