【问题标题】:"Namespaces", constants and multiple PHP includes“命名空间”、常量和多个 PHP 包括
【发布时间】:2010-10-27 07:46:57
【问题描述】:

我有一些类似于以下的 PHP 代码:

foreach ($settingsarray as $settingsfile)
{
    include ($settingsfile);
    // do stuff here
}

$settingsarray 是来自特定文件夹的文件名数组。

问题是,每个 $settingsfile 都定义了常量(同名),当然不能重新定义。

有哪些可能的方法来防止在这种情况下发生错误?

我能想到的两个选项包括,将所有常量更改为变量并使用 PHP 命名空间。

但是,我不确定如何使用命名空间,它需要在每个 $settingsfile 的开头声明?有没有不使用命名空间来隔离常量、变量和函数的方法?

我真正喜欢的是能够做一些简单的事情:

foreach ($settingsarray as $settingsfile)
{
    {//added braces to indicate where the isolation is
        include ($settingsfile);
        // do stuff here
    }//what happens in here does not affect what happens outside of here
}

我应该注意,这是新功能的一部分,并且是加载所有 $settingsfiles 的代码的唯一部分。其余代码一次只加载一个文件。我使用常量的一个原因是我不必担心定义“全局”变量以便能够在函数内部访问它们。

【问题讨论】:

    标签: php namespaces include


    【解决方案1】:

    我的回答有点复杂,但应该很适合你。我假设您有大量这些设置文件,因为您非常不愿意单独更改每个设置文件。

    如果您能够使用命名空间,我假设您已经升级到 PHP 5.3RC2。将以下内容复制到 .php 文件中,并根据自己的喜好更改命名空间:

    <?php
    namespace myapp\config;
    
    function define($key, $val) {
        Config::set($key, $val);
    }
    
    class Config {
        private $vars = array();
    
        // This class should not be instantiated
        private function __construct() {}
    
        public function set($key, $val) {
            self::$vars[$key] = $val;
        }
    
        public function get($key) {
            return isset(self::$vars[$key]) ? self::$vars[$key] : NULL;
        }
    }
    
    ?>
    

    将它包含在您的代码中,现在让一切正常工作只需更改

    <?php
    

    在你的设置文件中

    <?php namespace myapp\config;
    

    如果你有很多,你的终端中的快速“sed”命令应该可以很好地处理它,一举一动。

    如果我不知道如何使用我的代码,这里有一个例子:

    <?php
    require_once('the_php_file_i_just_gave_you.php');
    use \myapp\config\Config;
    
    foreach ($settingsarray as $settingsfile) {
        include ($settingsfile);
        $varname = 'key';
        echo "In this file, '$varname' equals: " . Config::get($varname);
    }
    
    ?>
    

    祝你好运!

    【讨论】:

      【解决方案2】:

      好的,如果我的理解正确,那么在该循环中,您希望使用每个 $settingsfile 中定义的常量来执行操作,然后在每个循环之后基本上摆脱它们?

      与变量不同,常量是一个值,一旦设置,就无法在脚本执行期间更改或取消设置 src

      您唯一的选择是将define() 声明更改为变量。

      【讨论】:

      • 你得到了我想做的正确的事情。解决方案,我不想听。 (程序实际上相当复杂,这段代码来自一项新功能。所有其余代码仅在特定时间加载一个设置文件。将所有常量更改为变量将意味着更改所有其余部分的代码以及...)
      【解决方案3】:

      不容易,但您可以使用 file_get_contents($settingsfile) 读取 php 文件,然后重写常量,并评估代码。

      $settingsstr = file_get_contents($settingsfile);
      $settingsstr = preg_replace('/<\?\w*(.*)/', '\\1', $settingsstr);//get rid of the php open tag
      $settingsstr = preg_replace('/define\("(\w+)"/', 'define("NAMESPACE_\\1"', $settingsstr);
      eval($settingsstr);
      

      【讨论】:

      • 这只是在尖叫“可怕的骇客”
      【解决方案4】:

      你有几个选择:

      使用 PHP 命名空间

      令人惊讶的是,PHP 确实支持namespaces。我很惊讶地发现这一点,因为我已经在 PHP 中工作多年并且从未听说过此功能。它可能是一个较新的功能,并且不常用,所以我建议不要使用这种方法

      使用类常量

      您可以使用类和class constants 来加载您的设置。类常量是定义类的本地常量,因此您无需担心类中的名称冲突。您可能需要做的不仅仅是包含文件,但您可以在每个类上调用一个方法,例如定义应用程序常量的 defineConstants() 或 loadConfiguration(),保留类常量供内部使用。

      使用功能扩展设置

      另一个想法是创建一个设置数组和单独的函数来“扩展”这些设置。这样您就可以在后续函数中覆盖任何配置而不会导致错误。最后,如果你想把它们放在常量中,你可以遍历数组并使用 define() 来定义常量。

      还有很多其他方法可以完成您想要做的事情,但这些只是一些想法。

      【讨论】:

      • 命名空间是 PHP 5.3 中的新功能,但尚未稳定发布。
      【解决方案5】:

      设置文件不应包含 PHP 代码。 它应该是某种“标准”格式。 http://www.php.net/parse_ini_file

      • 在第一步(在您的 foreach 中)您阅读所有文件
      • 将变量收集到一个临时数组中
      • 在此数组的另一个循环中,您可以将它们定义为常量。

      如果您经常觉得有必要“重新定义常量”,那么应用程序设计中就有问题。

      【讨论】:

      • 我不认为在 PHP 中定义设置有什么本质上的坏处。我不希望最终用户结束这些设置文件,但直接在 PHP 中编写设置对我来说效率更高。
      • 这是整个应用程序中我觉得需要重新定义常量的唯一部分。问题是,新功能。
      猜你喜欢
      • 2018-08-02
      • 1970-01-01
      • 2013-06-12
      • 2014-01-24
      • 2012-11-15
      • 1970-01-01
      • 2014-09-06
      • 2013-08-17
      • 2019-03-12
      相关资源
      最近更新 更多