【问题标题】:How does one specify a file path relative to the location of the config file when Zend_Config_Ini is in use?当使用 Zend_Config_Ini 时,如何指定相对于配置文件位置的文件路径?
【发布时间】:2012-01-08 01:56:23
【问题描述】:

我有一组通用功能,我想使用该应用程序的Zend_Config 实例中的configs 参数将其嵌入到Zend_Application 实例中。但是,从属配置文件希望能够引用相对于自身的路径中的事物。例如:

$/application/configs/application.ini:

[base]
config[] = APPLICATION_PATH "../CasCommon/Configs/common.ini

$/CasCommon/Configs/common.ini

[base]
resources.frontController.controllerDirectory[] = PATH_TO_THIS_IN_DIR "../Controllers"
resources.frontController.actionHelperPaths.Cas_Common_Helper = PATH_TO_THIS_IN_DIR "../ControllerHelpers"
;...

一个人怎么可能完成这样的事情?

【问题讨论】:

    标签: php zend-framework ini zend-application zend-config


    【解决方案1】:

    PHP 支持 Ini 文件中的常量,但不幸的是不支持魔术常量,所以不能使用 __DIR__,这样可以解决问题。最简单和最明显的事情是将 application.ini 文件的路径定义为常量,就像您对 APPLICATION_PATH 所做的那样,例如

    // application.ini
    foo = INI_PATH '/../somewhere/else'
    
    // index.php
    const INI_PATH = '/path/to/config/folder';
    

    然后只需定期加载您的Zend_Application 或实例化一个新的Zend_Config,然后将按照您的要求评估常量。

    在 cmets 之后编辑

    我发现关于上述内容的论点不够自动化。在标准 ZF 项目中,APPLICATION_PATH 定义在 index.php 文件中,这也是 default application.ini is loaded 所在的位置。您所要做的就是在此处添加常量。 Ini 文件本身并不存在,因此有人将不得不在某些时候调用外部库(可能您作为开发人员)。上述解决方案需要一行设置。任何其他解决方案都需要更多的工作。

    如果这对您来说还不够好,您可以扩展 Zend_Application 以在加载 application.ini 之前自动添加该常量:

    class My_Zend_Application extends Zend_Application
    {
        protected function _loadConfig($file)
        {
            if (!defined('PATH_TO_INI')) {
                define('PATH_TO_INI', dirname(realpath($file)));
            }
            return parent::_loadConfig($file);
        }
    }
    

    当然,您仍然需要更改 index.php 以使用扩展的 My_Zend_Application,这就是为什么我觉得这种方法毫无意义,因为您也可以在 index.php 文件中添加常量。

    自定义Zend_Application 当然会将您限制在 application.ini 中,因为您不能再在运行时更改常量。因此,如果您需要此功能用于多个 Ini 文件而不仅仅是 application.ini,请扩展 Zend_Config_Ini 并在返回之前检查每个值的相对路径标记,例如

    class My_Config_Ini extends Zend_Config_Ini
    {
        protected $_relativePath;
        protected $_relativePathMarker = '%REL_PATH%';
        public function __construct($filename, $section = null, $options = false)
        {
            $this->_relativePath = dirname(realpath($filename));
            parent::__construct($filename, $section, $options);
        }
        public function get($name, $default = null)
        {
            if (array_key_exists($name, $this->_data)) {
                return $this->_containsRelativePathMarker($this->_data[$name])
                    ? $this->_expandRelativePath($this->_data[$name])
                    : $this->_data[$name];
            }
            return $default;
        }
        protected function _containsRelativePathMarker($value)
        {
            return strpos($value, $this->_relativePathMarker) !== FALSE;
        }
        protected function _expandRelativePath($value)
        {
            return str_replace('%REL_PATH%', $this->_relativePath, $value);
        }
    }
    

    以上假设您使用类似的东西编写您的 Ini 文件

    foo = %REL_PATH% '/../foo.txt'
    

    如果这仍然不是您想要的,我只能再次鼓励您提出精确的要求。当您在这里不接受任何答案时,提供 500 声望是没有意义的,因为我们没有读懂您的想法。

    【讨论】:

    • 呸。我想它可以作为一种解决方法。也许我会构建一个 Zend_Application_Resource 来完成它......:/
    • 为什么糟糕?这是干净和简单的解决方案。鉴于您已经在使用 APPLICATION_PATH,为什么要发明一些额外的方法来实现这一点,而不是使用显而易见的 PATH_TO_THIS_IN_DIR 作为另一个常量?
    • 因为它迫使我让客户端调用外部库以使用外部配置。这样做的全部目的是允许某人在他们的配置中添加一行,并让一切工作开箱即用。
    【解决方案2】:

    另一个选项是(如果您将 allowModifications 选项设置为 true)是更改工作目录,然后更改文件夹的实际路径。甚至在加载文件后添加路径。

    $config = new Zend_Config_Ini('config.ini', 'section', array(
        'allowModifications' => true,
    ));
    $dir = getcwd();
    chdir('..');
    $config->path = realpath($config->path);
    chdir($dir);
    

    【讨论】:

    • 但这将如何在示例中显示的任何路径(如 OP 所示)之前自动添加?
    • @Gordon 它像手动一样自动设置常量并将其放入文件中
    • 怎么回事?如果我设置它会自动评估的常量,那么PATH_TO_THIS_IN_DIR "../Foo 将作为/path/to/../foo 返回。据我了解您的解决方案,您只是将路径配置变量添加到配置对象。
    猜你喜欢
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    • 2011-04-06
    • 2023-03-04
    • 1970-01-01
    • 2012-07-26
    相关资源
    最近更新 更多