PHP 中的全局变量是否被认为是不好的做法?如果是这样,为什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1557787/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are global variables in PHP considered bad practice? If so, why?
提问by KRTac
function foo () {
global $var;
// rest of code
}
In my small PHP projects I usually go the procedural way. I generally have a variable that contains the system configuration, and when I nead to access this variable in a function, I do global $var;.
在我的小型 PHP 项目中,我通常采用程序化的方式。我通常有一个包含系统配置的变量,当我需要在函数中访问这个变量时,我会使用global $var;.
Is this bad practice?
这是不好的做法吗?
回答by cletus
When people talk about global variables in other languages it means something different to what it does in PHP. That's because variables aren't reallyglobal in PHP. The scope of a typical PHP program is one HTTP request. Session variables actually have a wider scope than PHP "global" variables because they typically encompass many HTTP requests.
当人们在其他语言中谈论全局变量时,它的含义与 PHP 中的含义不同。那是因为变量在 PHP中并不是真正的全局变量。一个典型的 PHP 程序的范围是一个 HTTP 请求。会话变量实际上比 PHP 的“全局”变量具有更广泛的范围,因为它们通常包含许多 HTTP 请求。
Often (always?) you can call member functions in methods like preg_replace_callback()like this:
通常(总是?)你可以在这样的方法中调用成员函数preg_replace_callback():
preg_replace_callback('!pattern!', array($obj, 'method'), $str);
See callbacksfor more.
请参阅回调了解更多信息。
The point is that objects have been bolted onto PHP and in some ways lead to some awkwardness.
关键是对象已经被固定在 PHP 上,并且在某些方面会导致一些尴尬。
Don't concern yourself overly with applying standards or constructs from different languages to PHP. Another common pitfall is trying to turn PHP into a pure OOP language by sticking object models on top of everything.
不要过分担心将不同语言的标准或构造应用于 PHP。另一个常见的陷阱是试图通过将对象模型置于一切之上来将 PHP 转变为纯 OOP 语言。
Like anything else, use "global" variables, procedural code, a particular framework and OOP because it makes sense, solves a problem, reduces the amount of code you need to write or makes it more maintainable and easier to understand, not because you think you should.
像其他任何事情一样,使用“全局”变量、过程代码、特定框架和 OOP,因为它有意义、解决问题、减少您需要编写的代码量或使其更易于维护和更易于理解,而不是因为您认为你应该。
回答by rojoca
Global variables if not used carefully can make problems harder to find. Let's say you request a php script and you get a warning saying you're trying to access an index of an array that does not exist in some function.
全局变量如果不小心使用会使问题更难发现。假设您请求一个 php 脚本,并收到一条警告,提示您尝试访问某个函数中不存在的数组索引。
If the array you're trying to access is local to the function, you check the function to see if you have made a mistake there. It might be a problem with an input to the function so you check the places where the function is called.
如果您尝试访问的数组是函数的本地数组,则检查函数以查看是否在那里犯了错误。函数的输入可能有问题,因此您检查调用函数的位置。
But if that array is global, you need to check all the places where you use that global variable, and not only that, you have to figure out in what order those references to the global variable are accessed.
但是,如果该数组是全局的,则需要检查使用该全局变量的所有位置,不仅如此,还必须确定访问这些对全局变量的引用的顺序。
If you have a global variable in a piece of code it makes it difficult to isolate the functionality of that code. Why would you want to isolate functionality? So you can test it and reuse it elsewhere. If you have some code you don't need to test and won't need to reuse then using global variables is fine.
如果您在一段代码中有一个全局变量,则很难隔离该代码的功能。为什么要隔离功能?所以你可以测试它并在其他地方重用它。如果您有一些不需要测试并且不需要重用的代码,那么使用全局变量就可以了。
回答by Don Dickinson
i agree with cletus. i would add two things:
我同意 cletus。我要补充两点:
- use a prefix so you can immediately identify it as global (e.g. $g_)
- declare them in one spot, don't go sprinkling them all around the code.
- 使用前缀,以便您可以立即将其识别为全局(例如 $g_)
- 在一个地方声明它们,不要在代码周围散布它们。
best regards, don
最好的问候,唐
回答by Anthony Rutledge
Who can argue against experience, college degrees, and software engineering? Not me. I would only say that in developing object-oriented single page PHP applicatons, I have more fun when I know I can build the entire thing from scratch without worrying about namespace collisions. Building from scratch is something many people do not do anymore. They have a job, a deadline, a bonus, or a reputation to care about. These types tend to use so much pre-built code with high stakes, that they cannot risk using global variables at all.
谁能反对经验、大学学位和软件工程?不是我。我只想说,在开发面向对象的单页 PHP 应用程序时,当我知道我可以从头开始构建整个应用程序而不必担心命名空间冲突时,我会觉得更有趣。从头开始构建是许多人不再做的事情。他们有工作、截止日期、奖金或声誉需要关心。这些类型倾向于使用如此多的预先构建的高风险代码,以至于它们根本不能冒险使用全局变量。
It may be bad to use global variables, even if they are only used in the global area of a program, but let's not forget about those who just want to have fun and make something work.
使用全局变量可能不好,即使它们只在程序的全局区域中使用,但我们不要忘记那些只是想玩得开心并让一些东西工作的人。
If that means using a few variables (< 10) in the global namespace, that only get used in the global area of a program, so be it. Yes, yes, MVC, dependency injection, external code, blah, blah, blah, blah. But, if you have contained 99.99% of your code into namespaces and classes, and external code is sandboxed, the world will not end (I repeat, the world will not end) if you use a global variable.
如果这意味着在全局命名空间中使用几个变量 (< 10),那么它们只会在程序的全局区域中使用,就这样吧。是的,是的,MVC,依赖注入,外部代码,等等,等等,等等,等等。但是,如果您已将 99.99% 的代码包含在命名空间和类中,并且外部代码被沙箱化,那么如果您使用全局变量,世界将不会结束(我再说一遍,世界不会结束)。
Generally, I would not say using global variables is bad practice. I would say that using global variables (flags and such) outside of the global area of a program is asking for troubleand (in the long run) ill-advisedbecause you can lose track of their states rather easily. Also, I would say that the more you learn, the less reliant you will beon global variables because you will have experienced the "joy" of tracking down bugs associated with their use. This alone will incentivize you to find another way to solve the same problem. Coincidentally, this tends to push PHP people in the direction of learning how to use namespaces and classes (static members, etc ...).
一般来说,我不会说使用全局变量是不好的做法。我会说在程序的全局区域之外使用全局变量(标志等)是在自找麻烦并且(从长远来看)是不明智的,因为您很容易忘记它们的状态。另外,我想说的是,你学得越多,对全局变量的依赖就越小,因为你将体验到追踪与其使用相关的错误的“乐趣”。仅此一项就会激励您找到解决同一问题的另一种方法。巧合的是,这往往会促使 PHP 人员朝着学习如何使用命名空间和类(静态成员等)的方向发展。
The field of computer science is vast. If we scare everyone away from doing something because we label it bad, then they lose out on the fun of truly understanding the reasoning behind the label.
计算机科学的领域是广阔的。如果我们因为给某事贴上不好的标签而吓跑每个人,那么他们就会失去真正理解标签背后的推理的乐趣。
Use global variables if you must, but then see if you can solve the problem without them. Collisions, testing, and debugging mean more when you intimately understand the true nature of the problem, not just a description of the problem.
如果必须,请使用全局变量,然后看看是否可以在没有它们的情况下解决问题。当您深入了解问题的真实本质,而不仅仅是对问题的描述时,冲突、测试和调试意味着更多。
回答by Machavity
Reposted from the ended SO Documentation Beta
从结束的 SO 文档 Beta 版重新发布
We can illustrate this problem with the following pseudo-code
我们可以用下面的伪代码来说明这个问题
function foo() {
global $bob;
$bob->doSomething();
}
Your first question here is an obvious one
你的第一个问题很明显
Where did
$bobcome from?
哪儿
$bob来的呢?
Are you confused? Good. You've just learned why globals are confusing and considered a bad practice. If this were a real program, your next bit of fun is to go track down all instances of $boband hope you find the right one (this gets worse if $bobis used everywhere). Worse, if someone else goes and defines $bob(or you forgot and reused that variable) your code can break (in the above code example, having the wrong object, or no object at all, would cause a fatal error). Since virtually all PHP programs make use of code like include('file.php');your job maintaining code like this becomes exponentially harder the more files you add.
你困惑吗?好的。您刚刚了解了为什么全局变量令人困惑并被认为是一种不好的做法。如果这是一个真正的程序,那么您的下一个乐趣就是跟踪所有实例$bob并希望找到正确的实例(如果$bob到处使用,情况会变得更糟)。更糟糕的是,如果其他人去定义$bob(或者你忘记并重用了那个变量)你的代码可能会中断(在上面的代码示例中,有错误的对象,或者根本没有对象,会导致致命错误)。由于几乎所有 PHP 程序都使用像include('file.php');您的工作维护代码这样的代码,因此您添加的文件越多,难度就会呈指数级增长。
How do we avoid Globals?
我们如何避免全局变量?
The best way to avoid globals is a philosophy called Dependency Injection. This is where we pass the tools we need into the function or class.
避免全局变量的最佳方法是一种称为Dependency Injection的哲学。这是我们将需要的工具传递给函数或类的地方。
function foo(\Bar $bob) {
$bob->doSomething();
}
This is mucheasier to understand and maintain. There's no guessing where $bobwas set up because the caller is responsible for knowing that (it's passing us what we need to know). Better still, we can use type declarationsto restrict what's being passed. So we know that $bobis either an instance of the Barclass, or an instance of a child of Bar, meaning we know we can use the methods of that class. Combined with a standard autoloader (available since PHP 5.3), we can now go track down where Baris defined. PHP 7.0 or later includes expanded type declarations, where you can also use scalar types (like intor string).
这更容易理解和维护。无需猜测在哪里$bob设置,因为调用者负责知道这一点(它向我们传递了我们需要知道的信息)。更好的是,我们可以使用类型声明来限制传递的内容。所以我们知道它$bob要么是Bar类的实例,要么是 的子类的实例Bar,这意味着我们知道我们可以使用该类的方法。结合标准的自动加载器(自 PHP 5.3 起可用),我们现在可以追踪Bar定义的位置。PHP 7.0 或更高版本包含扩展类型声明,您还可以在其中使用标量类型(如int或string)。
回答by Jonas Lundman
As:
作为:
global $my_global;
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']
is bad practice (Like Wordpress $pagenow)... hmmm
是不好的做法(如 Wordpress $pagenow)......嗯
Concider this:
考虑一下:
$my-global = 'Transport me between functions';
is PHP errorBut:
是 PHP 错误但是:
$GLOBALS['my-global'] = 'Transport me between functions';
is NOTerror, hypens will not clashwith "common" user declared variables, like $pagenow. And Using UPPERCASE indicates a superglobal in use, easy to spot in code, or track with find in files
是不是错误,hypens不会发生冲突与“普通”用户声明的变量,像$pagenow。使用 UPPERCASE 表示正在使用的超全局变量,易于在代码中发现,或在文件中使用find 进行跟踪
I use hyphens, if Im lazy to build classes of everything for a single solution, like:
我使用连字符,如果我懒得为单个解决方案构建所有类,例如:
$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';
But In cases of a more wider use, I use ONEglobals as array:
但在更广泛使用的情况下,我使用ONE全局变量作为数组:
$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';
The latter is for me, good practiceon "cola light" objectives or use, instead of clutter with singleton classes each time to "cache" some data. Please make a comment if Im wrong or missing something stupid here...
后者对我来说是“可乐灯”目标或使用的良好实践,而不是每次都用单例类来“缓存”一些数据。如果我错了或在这里遗漏了一些愚蠢的东西,请发表评论......

