Zend Framework 2应用程序的配置发生在以下几个步骤:
在这篇教程中,我们将着眼于恰当的顺序以及如何约束它们。
开始模块装载,我们必须告诉Application实例有关有效的模块以及它们在哪里,随意提供一些信息给默认的模块监听器(例如:应用配置在哪里,以及什么文件被装载;是否缓存合并配置放在哪里,等等),随意ServiceManager播种。在本教程中我们称这个配置为系统配置(System Configuration)
当使用应用程序骨架(或者应用程序框架)时,系统配置(System Configuration)默认在config/application.config.php里。看上去类似下面的代码:
<?php return array( // This should be an array of module namespaces used in the application. 'modules' => array( 'Application', ), // These are various options for the listeners attached to the ModuleManager 'module_listener_options' => array( // This should be an array of paths in which modules reside. // If a string key is provided, the listener will consider that a module // namespace, the value of that key the specific path to that module's // Module class. 'module_paths' => array( './module', './vendor', ), // An array of paths from which to glob configuration files after // modules are loaded. These effectively overide configuration // provided by modules themselves. Paths may use GLOB_BRACE notation. 'config_glob_paths' => array( 'config/autoload/{,*.}{global,local}.php', ), // Whether or not to enable a configuration cache. // If enabled, the merged configuration will be cached and used in // subsequent requests. //'config_cache_enabled' => $booleanValue, // The key used to create the configuration cache file name. //'config_cache_key' => $stringKey, // Whether or not to enable a module class map cache. // If enabled, creates a module class map cache which will be used // by in future requests, to reduce the autoloading process. //'module_map_cache_enabled' => $booleanValue, // The key used to create the class map cache file name. //'module_map_cache_key' => $stringKey, // The path in which to cache merged configuration. //'cache_dir' => $stringPath, // Whether or not to enable modules dependency checking. // Enabled by default, prevents usage of modules that depend on other modules // that weren't loaded. // 'check_dependencies' => true, ), // Used to create an own service manager. May contain one or more child arrays. //'service_listener_options' => array( // array( // 'service_manager' => $stringServiceManagerName, // 'config_key' => $stringConfigKey, // 'interface' => $stringOptionalInterface, // 'method' => $stringRequiredMethodName, // ), // ) // Initial configuration with which to seed the ServiceManager. // Should be compatible with Zend\ServiceManager\Config. // 'service_manager' => array(), );
系统配置有关MVC的点点滴滴在在你系统之前运行并准备好了。配置通常是简报并且相当小巧的。
另外,立即使用的系统配置,并且没有合并任何其它的配置-也就是说它不能被其它模块覆盖。
这引导我们到我们第一个技巧:如何提供特定环境下的系统配置?
当你要改变一整套基于环境的模块时会发生什么?或者如果配置缓存基于环境被启用会发生什么?
就是这个原因我们在应用程序框架中提供的默认系统配置是使用PHP的;使用PHP来支持的意思是说通过编程来控制它。
作为一个例子,让我们做以下的要求:
要实现以上的要求,我们在我们的Web Server的配置中设置一个环境变量,在Apache中设置APP_ENV,要么在你系统级的apache.conf文件,要么在http.conf文件中输入类似以下命令,或者在你的虚拟主机中定义,也可以输入到.htaccess文件中
SetEnv "APP_ENV" "development"
对于其它的web server,查阅web server文档来确定如何设置环境变量
为了简化问题,我们假定环境是“生产”如果没有环境变量存在。
我们按照以下的代码修改config/application.config.php
<?php $env = getenv('APP_ENV') ?: 'production'; // Use the $env value to determine which modules to load $modules = array( 'Application', ); if ($env == 'development') { $modules[] = 'ZendDeveloperTools'; } return array( 'modules' => $modules, 'module_listener_options' => array( 'module_paths' => array( './module', './vendor', ), 'config_glob_paths' => array( 'config/autoload/{,*.}{global,local}.php', ), // Use the $env value to determine the state of the flag 'config_cache_enabled' => ($env == 'production'), 'config_cache_key' => 'app_config', // Use the $env value to determine the state of the flag 'module_map_cache_enabled' => ($env == 'production'), 'module_map_cache_key' => 'module_map', 'cache_dir' => 'data/config/', // Use the $env value to determine the state of the flag 'check_dependencies' => ($env != 'production'), ), );
这种方法给你带来了改变系统级设置的灵活性。
但是,如何在基于环境的情况下修改应用程序特定的设置(不是系统配置)?
有些时候你想要修改应用程序配置来调用一些东西,例如数据库适配器,log写入,缓存适配器以及更多机基于环境的东西。这些在服务管理器中具有代表性的托管可能在模块中被定义。你可以通过Zend\ModuleManager\Listener\ConfigListener在应用级别中重写它们,经过一个在系统配置(System Configuration)中指定的全局路径 - 在上例中的module_listener_options.config_glob_paths关键字。
它的默认值是config/autoload/{,*.}{global,local}.php。这个意思是说它会在config/autoload目录中按照以下的顺序寻找应用程序配置(Application Configuration)
这允许你在“全局”配置文件中定义应用程序级别的默认值,然后提交到版本控制系统中,特定环境下在“本地”配置文件中重写那些你会忽略版本控制的值。
这是一个非常好的开发解决方案,它允许你指定交替的配置,针对你的开发环境不用担心意外的部署。
然而,如果你有很多环境 - 例如一个“测试”或者“展现”环境 - 它们每个都有自己的特殊的重写?
再说一次,使用应用程序环境变量。我们可以稍稍的改变以下系统配置中的全局路径:
'config_glob_paths' => array( sprintf('config/autoload/{,*.}{global,%s,local}.php', $env) ),以上代码允许你为每个环境额外的定义应用程序配置文件;此外,只有当相应的环境被侦测到,这些配置才会被调用!
作为一个例子,考虑一下以下的配置文件结构树:
config/ autoload/ global.php local.php users.development.php users.testing.php users.local.php如果$env是testing,以下的文件将按照顺序被合并:
global.php users.testing.php local.php users.local.php注意:users.development.php没有被调用 - 因为它没有匹配全局模式!
此外,由于按照顺序调用,你可以预测哪些值会覆盖其它的值,让你可以在后来的调试中有选择性的覆盖。
注意:
在config/autoload/目录下的文件在模块配置之后被合并,具体信息见下个段落。我们有详细的说明,然而,设定应用程序配置(Application Configuration)的全局路径是在系统配置(System Configuration)中的(config/application.config.php)
模块的职责之一是为应用程序提供它们自己的配置。模块有两个一般的机制来实现这个。
首先,要么通过Zend\ModuleManager\Feature\ConfigProviderInterface实现和/或通过getConfig()方法返回模块的配置。默认,推荐使用getConfig()方法:
public function getConfig() { return include __DIR__ . '/config/module.config.php'; }
module.config.php返回一个PHP数组。
第二,模块能够实现许多接口和/或与指定的服务管理器或插件管理器配置有关的方法。例如:
接口名称 | 方法名称 |
ControllerPluginProviderInterface |
getControllerPluginConfig() |
ControllerProviderInterface |
getControllerConfig() |
FilterProviderInterface |
getFilterConfig() |
FormElementProviderInterface |
getFormElementConfig() |
HydratorProviderInterface |
getHydratorConfig() |
InputFilterProviderInterface |
getInputFilterConfig() |
RouteProviderInterface |
getRouteConfig() |
SerializerProviderInterface |
getSerializerConfig() |
ServiceProviderInterface |
getServiceConfig() |
ValidatorProviderInterface |
getValidatorConfig() |
ViewHelperProviderInterface |
getViewHelperConfig() |
所有的接口列表都在Zend\ModuleManager\Feature命名空间中,每个都为服务管理器返回一个配置数组,在“默认服务管理”中有提到。
考虑到你可能会在模块配置文件中含有服务配置,哪一个优先?
合并的顺序是:
换句话说,你各种服务配置方法优先。另外特别注意:从方法中返回的配置不会被缓存。原因是它不是经常使用闭包或者工厂实例从你的模块类返回配置 - 不能可靠的缓存配置。
注意:
当你需要定义闭包或者为工厂模式定义回调接口,抽象工厂和初始化时使用各种服务配置方法,这预防了缓存问题,同时也允许你使用其它格式写你自己的配置文件。
在结束本教程之前,让我们回顾一下如何以及何时定义以及合并配置。
系统配置(System Configuration) - 在config/application.config.php中定义 - 不会合并 - 允许以编程方式操作,允许:
应用程序配置(Application Configuration) - ModuleManager按照定义的顺序循环访问每个模块类
在系统配置(System Configuration)中 - 定义在模块类中的服务配置是聚合 - 通过Module::getConfig()返回的配置是聚合
未完待续,谢谢......