【问题标题】:PHP: Globals, SuperGlobals - How to make a variable's value accessible to all functions?PHP: Globals, SuperGlobals - 如何让所有函数都能访问变量的值?
【发布时间】:2025-12-16 01:35:01
【问题描述】:

我正在编写一个大约 200 行代码的 PHP 程序。它有很多我写的函数,可能有十几个。我想在程序中有一个调试选项,但也希望在所有函数中都可以访问该值。这应该如何以及在哪里定义?

Global $debug_status;

function blah ($message) {
if ($debug_status == "1" ) {
  do something...}
...
}

这是正确的方法吗?谢谢!

【问题讨论】:

  • 不要使用Globlas你可以使用Registry Pattern来实现。检查此线程*.com/questions/8147207/php-registry-pattern
  • 我应该提一下,这个程序不是面向对象的。这有关系吗?
  • 您可以使用常量,因为它们不受范围的约束。
  • 你能举个例子吗?
  • define('DEBUG_STATUS', 1);DEBUG_STATUS 可以从任何地方访问所有底部代码行。

标签: php global-variables


【解决方案1】:

使用常量。

define('DEBUG', true);

...

if (DEBUG) ...

当然还有更好的调试方法。例如,使用 OOP,将记录器实例注入到每个对象中,调用

$this->logger->debug(...);

要记录消息,请切换记录器的输出过滤器以显示或隐藏调试消息。

【讨论】:

    【解决方案2】:

    你快到了.... global 关键字将对全局的引用导入当前范围。

    $debug_status = "ERROR";
    
    function blah ($message) {
        global $debug_status;
        if ($debug_status == "1" ) {
          do something...}
          ...
        }
    

    【讨论】:

    • 所以你必须在每个函数内部定义变量global?
    • 正确...另一种选择是您可以通过$GLOBALS["debug_status"] 从全局超级全局访问它,但这两种技术都完全忽略了范围和它提供的好处。
    【解决方案3】:

    变量应该在注册表类中定义,这是一种模式。

    Working demo

    注册表示例

    class Registry {
       private static $registry = array();
    
       private function __construct() {} //the object can be created only within a class.
       public static function set($key, $value) { // method to set variables/objects to registry
          self::$registry[$key] = $value;
       }
    
       public static function get($key) { //method to get variable if it exists from registry
          return isset(self::$registry[$key]) ? self::$registry[$key] : null;
       }
    }
    

    用法

    要注册对象,你需要包含这个类n

    $registry::set('debug_status', $debug_status); //this line sets object in **registry**
    

    要获取对象,您可以使用 get 方法

    $debug_status = $registry::get('debug_status'); //this line gets the object from **registry**
    

    这是可以存储每个对象/变量的解决方案。对于您所写的目的,最好使用简单的常量和define()

    我的解决方案适用于应从应用程序中的任何位置访问的各种对象。

    编辑

    删除了单例和 make get,将方法设置为 @deceze 建议的静态方法。

    【讨论】:

    • 为什么不把整个Registry 和它的所有方法都做成static?为什么要通过静态获取实例来获取密钥的麻烦,为什么不直接Registry::get('debug_status')?似乎是两全其美。 →How Not To Kill Your Testability Using Statics.
    • 显然可以使用静态方法来完成,但是两种解决方案的工作方式没有区别。你建议的更短,可能更好:)
    • 我已经按照@deceze 的建议使用静态方法更改了解决方案。