KRT*_*Tac 84 php global global-variables
function foo () {
global $var;
// rest of code
}
Run Code Online (Sandbox Code Playgroud)
在我的小PHP项目中,我通常采用程序方式.我通常有一个包含系统配置的变量,当我需要在函数中访问此变量时,我会这样做global $var;
.
这是不好的做法吗?
cle*_*tus 99
当人们谈论其他语言中的全局变量时,它意味着与PHP中的变量不同.那是因为PHP中的变量并不是真正的全局变量.典型PHP程序的范围是一个HTTP请求.会话变量实际上具有比PHP"全局"变量更广的范围,因为它们通常包含许多HTTP请求.
通常(总是?)你可以用这样的方法调用成员函数preg_replace_callback()
:
preg_replace_callback('!pattern!', array($obj, 'method'), $str);
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅回调.
重点是对象已经用螺栓固定在PHP上,并在某些方面导致一些尴尬.
不要过分关注将不同语言的标准或构造应用于PHP.另一个常见的陷阱是试图通过将对象模型放在所有内容之上来将PHP转换为纯OOP语言.
像其他任何东西一样,使用"全局"变量,过程代码,特定框架和OOP,因为它有意义,解决问题,减少您需要编写的代码量或使其更易于维护和更易于理解,而不是因为您认为你应该.
roj*_*oca 27
如果不仔细使用全局变量会使问题更难找到.假设您请求一个php脚本,并且您收到一条警告,说您正在尝试访问某个函数中不存在的数组的索引.
如果您尝试访问的数组是函数的本地数组,则检查函数以查看是否在那里犯了错误.输入函数可能会出现问题,因此您需要检查函数调用的位置.
但是如果该数组是全局的,则需要检查使用该全局变量的所有位置,不仅如此,您还必须弄清楚这些对全局变量的引用的访问顺序.
如果在一段代码中有一个全局变量,则很难隔离该代码的功能.为什么要隔离功能?所以你可以测试它并在其他地方重复使用它.如果您有一些代码,您不需要测试,也不需要重用,那么使用全局变量就可以了.
Don*_*son 16
我同意cletus.我会添加两件事:
最好的问候,不要
谁可以反对经验,大学学位和软件工程?不是我。我只想说,在开发面向对象的单页面PHP应用程序时,当我知道我可以从头开始构建整个过程而不必担心命名空间冲突时,我会感到更加开心。从头开始构建是许多人不再要做的事情。他们有工作,有最后期限,有奖金或有名望。这些类型倾向于使用大量高风险的预构建代码,以至于完全没有使用全局变量的风险。
即使只在程序的全局区域中使用全局变量,也可能会很糟糕,但不要忘了那些只想获得乐趣并使某事起作用的人。
如果这意味着在全局名称空间中使用几个变量(<10),则只能在程序的全局区域中使用它,那就这样吧。是的,是的,MVC,依赖项注入,外部代码,等等,等等,等等。但是,如果您已经将99.99%的代码包含在名称空间和类中,并且外部代码被沙盒化,则使用全局变量的世界将不会结束(我再说一遍,世界不会结束)。
通常,我不会说使用全局变量是不好的做法。我要说的是,在程序的全局区域之外使用全局变量(标志等)会带来麻烦,并且从长远来看是不明智的,因为您可以很容易地跟踪它们的状态。另外,我想说的是,您学得越多,对全局变量的依赖就越少,因为您将体验到“追踪”与使用它们相关的错误的“乐趣”。仅此一项就可以激励您找到解决同一问题的另一种方法。巧合的是,这倾向于将PHP推向学习如何使用名称空间和类(静态成员等)的方向。
计算机科学领域广阔。如果我们因为标记不好而使每个人都害怕做某事,那么他们就会失去真正理解标签背后原因的乐趣。
如果需要,请使用全局变量,然后查看是否可以在没有全局变量的情况下解决问题。当您深入了解问题的真实本质时,冲突,测试和调试的意义就更大了,而不仅仅是对问题的描述。
从结束的 SO 文档 Beta 版重新发布
我们可以用下面的伪代码来说明这个问题
function foo() {
global $bob;
$bob->doSomething();
}
Run Code Online (Sandbox Code Playgroud)
你的第一个问题很明显
哪儿
$bob
来的呢?
你困惑吗?好的。您刚刚了解了为什么全局变量令人困惑并被认为是一种不好的做法。如果这是一个真正的程序,那么您的下一个乐趣就是跟踪所有实例$bob
并希望找到正确的实例(如果$bob
到处使用,情况会变得更糟)。更糟糕的是,如果其他人去定义$bob
(或者你忘记并重用了那个变量)你的代码可能会中断(在上面的代码示例中,有错误的对象,或者根本没有对象,会导致致命错误)。由于几乎所有 PHP 程序都使用像include('file.php');
您的工作维护代码这样的代码,因此您添加的文件越多,难度就会呈指数级增长。
我们如何避免全局变量?
避免全局变量的最佳方法是一种称为Dependency Injection的哲学。这是我们将需要的工具传递给函数或类的地方。
function foo(\Bar $bob) {
$bob->doSomething();
}
Run Code Online (Sandbox Code Playgroud)
这更容易理解和维护。无需猜测在哪里$bob
设置,因为调用者负责知道这一点(它向我们传递了我们需要知道的信息)。更好的是,我们可以使用类型声明来限制传递的内容。所以我们知道它$bob
要么是Bar
类的实例,要么是 的子类的实例Bar
,这意味着我们知道我们可以使用该类的方法。结合标准的自动加载器(自 PHP 5.3 起可用),我们现在可以追踪Bar
定义的位置。PHP 7.0 或更高版本包含扩展类型声明,您还可以在其中使用标量类型(如int
或string
)。