PHP中的全局variables被认为是不好的做法? 如果是这样,为什么?

function foo () { global $var; // rest of code } 

在我的小型PHP项目中,我通常采取程序化的方式。 我通常有一个variables,其中包含系统configuration,当我nead访问函数中的这个variables,我做global $var;

这是不好的做法?

当人们谈论其他语言的全局variables时,它意味着与PHP中的不同。 这是因为PHP中的variables不是全球性的。 一个典型的PHP程序的范围是一个HTTP请求。 会话variables实际上比PHP“全局”variables具有更广的范围,因为它们通常包含许多HTTP请求。

通常(总是?),你可以像preg_replace_callback()这样的方法调用成员函数:

 preg_replace_callback('!pattern!', array($obj, 'method'), $str); 

看到更多的callback 。

关键是对象已经被锚定到PHP,并在某些方面导致一些尴尬。

不要过分关注将不同语言的标准或结构应用于PHP。 另一个常见的错误是试图通过将对象模型粘贴到所有东西上来将PHP变成纯粹的OOP语言。

像其他任何东西一样,使用“全局”variables,过程代码,特定的框架和面向对象,因为它是有意义的,解决了一个问题,减less了需要编写的代码数量或使其更容易理解,而不是因为你认为你应该。

如果不小心使用全局variables,可能会使问题更难以find。 比方说,你要求一个PHP脚本,你会得到一个警告,说你试图访问某个函数中不存在的数组的索引。

如果你试图访问的数组是本地的函数,你检查函数,看看你是否犯了一个错误。 这可能是一个input到函数的问题,所以你检查函数被调用的地方。

但是如果这个数组是全局的,那么你需要检查你使用这个全局variables的所有地方,而不仅仅是这个,你必须弄清楚这个全局variables的引用是以什么顺序访问的。

如果你在一段代码中有一个全局variables,那么就很难隔离代码的function。 你为什么要分离function? 所以你可以testing它并在别处重用。 如果你有一些代码,你不需要testing,也不需要重用,那么使用全局variables是没有问题的。

我同意cletus。 我会添加两件事情:

  1. 使用一个前缀,所以你可以立即将其识别为全局(例如$ g_)
  2. 在一个地方宣布他们,不要把它们全部撒在代码周围。

最好的问候,不要

谁可以反对经验,大学学位和软件工程? 不是我。 我只想说,在开发面向对象的单页PHP应用程序时,我知道我可以从零开始构build整个事情,而不用担心命名空间冲突,所以我获得了更多的乐趣。 从头开始是许多人不再做的事情。 他们有一份工作,一个期限,一个奖金,或一个关心的声誉。 这些types倾向于使用大量的预build代码,而且风险高,所以他们根本无法冒险使用全局variables。

即使全局variables只用在程序的全局区域,使用全局variables可能也不好,但是我们不要忘记那些只是为了获得乐趣而努力工作的人

如果这意味着在全局命名空间中使用一些variables(<10),那么只能在程序的全局区域中使用,就这样做。 是的,是的,MVC,dependency injection,外部代码,等等,等等,等等等等。 但是,如果你已经将99.99%的代码包含在命名空间和类中,并且外部代码被沙盒化了,那么如果你使用全局variables的话,世界将不会结束(我再说一遍,世界将不会结束)。

一般来说,我不会说使用全局variables是不好的做法 。 我会说,在一个程序的全球范围之外使用全局variables(标志等)是在寻找麻烦,而且(从长远来看)是不明智的,因为你可以很容易地忽略它们的状态。 另外,我会说, 你学的越多,对全局variables的依赖就越less,因为你将会体验到追踪与其使用相关的错误的“快乐”。 只有这一点,才能激励你find另一种解决同样问题的方法。 巧合的是,这往往会推动PHP人员学习如何使用名称空间和类(静态成员等)的方向。

计算机科学领域广阔。 如果我们把每个人都吓跑,因为我们标签不好 ,那么他们就失去了真正理解标签背后原因的乐趣。

如果必须,请使用全局variables,但是如果没有这些variables,请查看是否可以解决问题。 碰撞,testing和debugging意味着更多,当你深刻理解问题的本质,而不仅仅是一个问题的描述。

从已结束的SO文档Beta转发

我们可以用下面的伪代码来说明这个问题

 function foo() { global $bob; $bob->doSomething(); } 

你的第一个问题是一个明显的问题

$bob从哪里来?

你困惑吗? 好。 你刚刚知道为什么全局变得混乱,被认为是不好的做法。 如果这是一个真正的程序,那么你的下一个乐趣就是追踪$bob所有实例,并希望find正确的(如果在任何地方使用$bob这会变得更糟糕)。 更糟糕的是,如果别人去定义$bob (或者你忘记和重用了这个variables),你的代码可能会中断(在上面的代码示例中,有错误的对象或者根本没有对象会导致严重的错误)。 由于几乎所有的PHP程序都使用include('file.php');这样的代码include('file.php'); 像这样维护代码的工作变得越来越困难,你添加的文件越多。

我们如何避免全局?

避免全局性的最好方法是称为dependency injectionDependency Injection )的理念。 这是我们将需要的工具传递给函数或类的地方。

 function foo(\Bar $bob) { $bob->doSomething(); } 

容易理解和维护。 没有猜测$bob设置,因为调用者负责知道(它传递给我们我们需要知道的)。 更好的是,我们可以使用types声明来限制正在传递的内容。 所以我们知道$bob既可以是Bar类的一个实例,也可以是Bar的一个子实例,这意味着我们可以使用这个类的方法。 结合标准自动加载器(自PHP 5.3起可用),我们现在可以追踪Bar定义的位置。 PHP 7.0或更高版本包含扩展types声明,您也可以使用标量types(如intstring )。

如:

 global $my_global; $my_global = 'Transport me between functions'; Equals $GLOBALS['my_global'] 

是不好的做法(像WordPress的$pagenow )…嗯

Concider这个:

 $my-global = 'Transport me between functions'; 

是PHP错误但是:

 $GLOBALS['my-global'] = 'Transport me between functions'; 

不是错误, hypens不会与“普通”用户声明的variables,如$pagenow 。 使用大写字母表示超全局使用,易于在代码中查找 ,或跟踪查找文件

我使用连字符,如果我懒惰build立一个单一的解决scheme的类,如:

 $GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... '; 

但在更广泛的使用情况下,我使用一个全局variables作为数组:

 $GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... '; $GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... '; 

后者对我来说是一个很好的练习 “可乐光”的目标或者用法,而不是每次都用单一类来混乱来“caching”一些数据。 如果我错了或在这里错过了一些愚蠢的东西,请发表评论…