菜菜鸟Zend Framework 2 不完全学习涂鸦(十五)-- 高级配置技巧

高级配置技巧

Zend Framework 2应用程序的配置发生在以下几个步骤:

  • 初始配置通过Application实例和使用ModuleManager和ServiceManager的种子。在这篇教程中,我们称这个配置:系统配置(System Configuration)
  • 当有模块调用时ModuleManager的ConfigListener集合配置和合并它。在这篇教程中,我们称这个配置:应用配置(Application Configuration)
  • 一旦从所有模块中聚合配置,ConfigListener还将在指定目录中合并全局应用配置(典型目录是config/autoload/)

在这篇教程中,我们将着眼于恰当的顺序以及如何约束它们。

一、系统配置(System Configuration

开始模块装载,我们必须告诉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来支持的意思是说通过编程来控制它。

作为一个例子,让我们做以下的要求:

  • 我们要求只在开发阶段使用ZendDeveloperTools模块
  • 我们要求只在生产中有配置缓存

要实现以上的要求,我们在我们的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)

  • global.php
  • *.global.php
  • local.php
  • *.local.php

这允许你在“全局”配置文件中定义应用程序级别的默认值,然后提交到版本控制系统中,特定环境下在“本地”配置文件中重写那些你会忽略版本控制的值。

这是一个非常好的开发解决方案,它允许你指定交替的配置,针对你的开发环境不用担心意外的部署。

然而,如果你有很多环境 - 例如一个“测试”或者“展现”环境 - 它们每个都有自己的特殊的重写?

再说一次,使用应用程序环境变量。我们可以稍稍的改变以下系统配置中的全局路径:

'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命名空间中,每个都为服务管理器返回一个配置数组,在“默认服务管理”中有提到。

考虑到你可能会在模块配置文件中含有服务配置,哪一个优先?

合并的顺序是:

  • getConfig()返回的配置
  • 在模块类中通过各种服务配置方法返回的配置

换句话说,你各种服务配置方法优先。另外特别注意:从方法中返回的配置不会被缓存。原因是它不是经常使用闭包或者工厂实例从你的模块类返回配置 - 不能可靠的缓存配置。

注意:

当你需要定义闭包或者为工厂模式定义回调接口,抽象工厂和初始化时使用各种服务配置方法,这预防了缓存问题,同时也允许你使用其它格式写你自己的配置文件。

五、合并配置工作流程

在结束本教程之前,让我们回顾一下如何以及何时定义以及合并配置。

系统配置(System Configuration) - 在config/application.config.php中定义 - 不会合并 - 允许以编程方式操作,允许:

  • 在计算值的基础上改变标记
  • 在计算值的基础上改变配置全局路径
  • 配置被传递给Application接口,然后ModuleManager按照顺序初始化系统

应用程序配置(Application Configuration) - ModuleManager按照定义的顺序循环访问每个模块类

系统配置(System Configuration)中 - 定义在模块类中的服务配置是聚合 - 通过Module::getConfig()返回的配置是聚合

  • 服务配置(Service Configuration)config_glob_paths设置中发现的文件会被合并,合并的顺序是根据它们在全局路径中的顺序。
  • 合并后的配置最终被传递给ServiceManager



未完待续,谢谢......

你可能感兴趣的:(框架,PHP,zendframework2)