function foo () {
global $var;
// rest of code
}
在我的小PHP项目中,我通常采用程序方式。我通常有一个包含系统配置的变量,当我需要在函数中访问此变量时,我会global $var;
。
这是不好的做法吗?
答案 0 :(得分:95)
当人们谈论其他语言中的全局变量时,它意味着与PHP中的变量不同。那是因为PHP中的变量不是真正的全局。典型PHP程序的范围是一个HTTP请求。会话变量实际上具有比PHP“全局”变量更广的范围,因为它们通常包含许多HTTP请求。
通常(总是?)你可以像preg_replace_callback()
这样的方法调用成员函数:
preg_replace_callback('!pattern!', array($obj, 'method'), $str);
有关详情,请参阅callbacks。
关键是对象已经用螺栓固定在PHP上,并在某些方面导致一些尴尬。
不要过分关注将不同语言的标准或构造应用于PHP。另一个常见的陷阱是试图通过将对象模型放在所有内容之上来将PHP转换为纯OOP语言。
与其他任何东西一样,使用“全局”变量,过程代码,特定框架和OOP,因为它有意义,解决问题,减少需要编写的代码量或使其更易于维护和更易于理解,而不是因为你认为你应该这样做。
答案 1 :(得分:25)
如果不仔细使用全局变量会使问题更难找到。假设您请求一个php脚本,并且您收到一条警告,说您正在尝试访问某个函数中不存在的数组的索引。
如果您尝试访问的阵列是该功能的本地阵列,则检查该功能以查看您是否在那里犯了错误。输入函数可能会出现问题,因此您需要检查函数调用的位置。
但是如果该数组是全局的,则需要检查使用该全局变量的所有位置,不仅如此,您还必须弄清楚对全局变量的引用的访问顺序。
如果在一段代码中有一个全局变量,则很难隔离该代码的功能。为什么要隔离功能?所以你可以测试它并在其他地方重复使用它。如果你有一些代码,你不需要测试,也不需要重用,那么使用全局变量就可以了。
答案 2 :(得分:16)
我同意cletus。我会添加两件事:
最好的问候, 别
答案 3 :(得分:4)
谁可以反对经验,大学学位和软件工程?不是我。我只想说在开发面向对象的单页PHP应用程序时,当我知道我可以从头开始构建整个事物而不用担心命名空间冲突时,我会更有乐趣。从头开始构建是许多人不再做的事情。他们有工作,截止日期,奖金或关注的声誉。这些类型倾向于使用如此多的具有高风险的预构建代码,它们根本不会冒使用全局变量的风险。
使用全局变量可能不好,即使它们仅用于程序的全局区域,但是不要忘记那些只是想要获得乐趣并使某些工作成功的人< / em>的
如果这意味着在全局命名空间中使用一些变量(&lt; 10),那只能在程序的全局区域中使用,那就这样吧。是的,是的,MVC,依赖注入,外部代码,等等,等等,等等等等。但是,如果你将99.99%的代码包含在命名空间和类中,并且外部代码是沙盒的,那么如果使用全局变量,世界将不会结束(我重申,世界不会结束)。
一般来说,我不会说使用全局变量是不良做法。我会说在程序的全局区域之外使用全局变量(标志等)是要求麻烦和(从长远来看)不明智的因为你可以很容易地失去他们的状态。另外,我会说你学的越多,你对全局变量的依赖性就越小,因为你将体验到&#34; joy&#34;追踪与其使用相关的错误。仅此一项就可以激励您找到解决同一问题的另一种方法。巧合的是,这往往会推动PHP人员学习如何使用命名空间和类(静态成员等)。
计算机科学领域非常广泛。如果我们因为我们将其标记为 bad 而吓跑所有人,那么他们就会失去真正了解标签背后推理的乐趣。
如果必须,请使用全局变量,但是看看是否可以在没有它们的情况下解决问题。当您非常了解问题的真实性质时,碰撞,测试和调试意味着更多,而不仅仅是对问题的描述。
答案 4 :(得分:0)
如:
global $my_global;
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']
是不好的做法(如Wordpress $pagenow
)...嗯......
Concider this:
$my-global = 'Transport me between functions';
是PHP错误但是:
$GLOBALS['my-global'] = 'Transport me between functions';
NOT 错误,超赞不会与“常见”用户声明的变量发生冲突,例如$pagenow
。并且使用大写表示正在使用的超全局,易于在代码中找到,或使用在文件中查找
我使用连字符,如果我懒于为单个解决方案构建所有类的类,例如:
$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';
但是在更广泛使用的情况下,我使用 ONE 全局变量作为数组:
$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';
后者适合我,良好实践关于“可乐光”目标或使用,而不是每次都用单个类来“缓存”某些数据。如果我错了或遗漏了一些愚蠢的东西,请发表评论...
答案 5 :(得分:-1)
从已结束的SO文档测试版
转发
我们可以使用以下伪代码
来说明此问题function foo() {
global $bob;
$bob->doSomething();
}
这里的第一个问题很明显
你感到困惑吗?好。你刚刚了解了为什么全局变量令人困惑并被认为是一种不好的做法。如果这是一个真实的程序,那么下一步的乐趣就是追踪
$bob
来自哪里?
$bob
的所有实例,并希望找到合适的实例(如果到处使用$bob
,这会变得更糟)。更糟糕的是,如果其他人去定义$bob
(或者您忘记并重用该变量),您的代码可能会中断(在上面的代码示例中,有错误的对象,或根本没有对象,会导致致命的错误) 。由于几乎所有的PHP程序都使用像include('file.php');
这样的代码,因此您添加的文件越多,这样的工作维护代码就会越来越难。
我们如何避免Globals?
避免全局变量的最佳方法是一种名为 Dependency Injection 的哲学。这是我们将所需工具传递给函数或类的地方。
function foo(\Bar $bob) {
$bob->doSomething();
}
更容易理解和维护。没有猜测$bob
的设置位置,因为调用者有责任知道(它正在传递给我们我们需要知道的东西)。更好的是,我们可以使用type declarations来限制传递的内容。所以我们知道$bob
或者是Bar
类的实例,或者是Bar
的子实例,这意味着我们知道我们可以使用该类的方法。结合标准自动加载器(自PHP 5.3开始提供),我们现在可以跟踪定义Bar
的位置。 PHP 7.0或更高版本包括扩展类型声明,您还可以使用标量类型(如int
或string
)。