如何在Zend_Config_Ini正在使用时指定相对于配置文件位置的文件路径?

问题描述:

我已经使用该应用的Zend_Config实例中的configs参数将一组共同的功能嵌入Zend_Application实例中。但是,从属配置文件希望能够引用相对于其自身的路径中的东西。例如:如何在Zend_Config_Ini正在使用时指定相对于配置文件位置的文件路径?

$ /应用/ 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支持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和像你想的不断进行评估。评论后

编辑

我找到上面这样的说法没有被足够AUTOMAGIC实际意义。在一个标准的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点声望就没有意义了,因为我们没有读懂你的想法。

+0

Yuck。我想它是一个解决方法。也许我会建立一个Zend_Application_Resource来执行它...:/ –

+0

为什么Yuck?这是干净而简单的解决方案。考虑到你已经在使用'APPLICATION_PATH',为什么要用另外一个常量来创造一些额外的方法来实现这一点呢?使用明显的'PATH_TO_THIS_IN_DIR'作为另一个常量? – Gordon

+0

因为它迫使我让客户端调用外部库来使用外部配置。整个过程就是允许某人在他们的配置中添加一行,并让所有的东西都可以使用。 –

另一种选择是(如果您将allowModifications选项设置为true)是更改工作目录,然后实时路径文件夹。或者甚至在加载文件之后预先加载路径。

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

但是在这个例子中的OP等任何路径显示之前,这会如何自动预先加载? – Gordon

+0

@Gordon它像自动手动设置常量并将其放入文件 – Petah

+0

怎么样?如果我设置常量,它会自动评估,所以'PATH_TO_THIS_IN_DIR“../ Foo将作为'/ path/to /../ foo'返回。就我理解你的解决方案而言,你只是添加一条路径配置变量配置对象。 – Gordon