How to use the global.php/local.php configs in the

2020-02-26 02:34发布

问题:

In a ZF2 application I have some cofigs, that: 1. need to be different dependening on the environment; 2. are specific for a concrete module. I'm curently using it like here described:

global.php & local.php

return array(
    ...
    'modules' => array(
        'Cache' => array(
            'ttl' => 1, // 1 second
        )
    )
    ...
);

Module class

Module {
    ...
    public function getServiceConfig() {
        try {
            return array (
                'factories' => array(
                    'Zend\Cache\Adapter\MemcachedOptions' => function ($serviceManager) {
                        return new MemcachedOptions(array(
                            'ttl'           => $this->getConfig()['modules']['Cache']['ttl'],
                            ...
                        ));
                    },
                    ...
                )
            );
        }
        ...
    }
    ...
}

It's working fine, but I believe, that the module specific settings should be accessed over one central place in the module -- the getConfig() method of the Module class. Like this:

class Module {

    public function getConfig() {
        $moduleConfig = include __DIR__ . '/config/module.config.php';
        $application = $this->getApplicationSomehow(); // <-- how?
        $applicationModuleConfig = $application->getConfig()['modules'][__NAMESPACE__];
        $config = array_merge($moduleConfig, $applicationModuleConfig);
        return $config;
    }
    ...
    public function getServiceConfig() {
        try {
            return array (
                'factories' => array(
                    'Zend\Cache\Adapter\MemcachedOptions' => function ($serviceManager) {
                        return new MemcachedOptions(array(
                            'ttl'            => $serviceManager->get('Config')['modules']['Cache']['ttl'],
                            ...
                        ));
                    },
                    ...
                )
            );
        }
        ...
    }
    ...
}

The problem is, that I don't get, how to access the global.php/local.php configs in the getConfig() of a module. How can I do it?

回答1:

Every single configuration of every single loaded Module will be merged into one single config. Namely this would be:

$serviceManager->get('config');

The reason behind (global|local).config.php is merely for usage purpose. Global configuration files should always be deployed. Local configuration files however should only be deployed as distributionables, alias local.config.php.dist.

Distributionals will not be loaded, no matter where they are places. However common notion of ZF2 is to copy the distributionables into the /config/autoload-directory of the ZF2 Application and rename them to local.config.php

One example:

// YourModule/config/module.config.php
return array(
    'key' => 1337
);

// YourModule/config/local.yourmodule.php.dist
return array(
    'key' => 7331
);

Now when you publish / deploy your application, only module.config.php will be used. If someone wants to change the configuration of your Module, they would never touch module.config.php, as this file would constantly be overwritten when your module will be updated.

However what people can do is to copy:

YourModule/config/local.yourmodule.php.dist
to
/config/autoload/local.yourmodule.php

And change the config values inside this local configuration.

To understand:

  • You should always configure your module as best as possible for a LIVE-Scenario.
  • If you have environment-specific needs, overwrite this config using a local-config
  • local configs are never deployed automatically, this is a manual task needing to be done from inside the environment itself

Hope this got a little more clear

Ultimately:

  • configure your module for a LIVE-Scenario
  • On your development machine create a /config/autoload/mymodule.local.php and overwrite your ttl with it's development value

LoadOrder:

The last interesting part, which i have completely forgotten about, would be the load order of the configuration files. As all files are merged, this is important to note!

  • First to load is /config/application.config.php
  • Second to load would be each Modules /modules/{module}/config/module.config.php *
  • Last but not least the autoloadable files will be loaded /config/autoload/{filename}.php

asterix It is actually NOT module.config.php which is called, but rather the Module-classes configuration functions. Mainly these are:

  • getConfig()
  • getServiceConfig()
  • getViewHelperConfig()
  • ultimately everything under Zend\ModuleManager\Feature\{feature}ProviderInterface

If i understand this part of the ConfigListener correctly, then getConfig() will be called first and all of the specialiced {feature}ProviderInterfaces will overwrite the data of getConfig(), but don't take this for granted, it would need a check!



回答2:

You're not supposed to access other Modules setting in your Module#getConfig(). If you rely on other configuration, that CAN ONLY BE for service purposes. Ergo you'd rely on Module#getServiceConfig() and inside the factories you do have access to the ServiceManagerand access your configs with $serviceManager->get('config');. (see Sam's comment)

The loading order of the configs is by default:

  1. /config/application.config.php, that is the initial config file; not for module configs; here is the filename pattern for the config files to load defined ('config_glob_paths' => array('config/autoload/{,*.}{global,local}.php')).
  2. {ModuleNamespace}\Module#getConfig() (e.g. Cache\Module#getConfig()), that by convention should load its /module/{ModuleNamespace}/config/module.config.php;
  3. /config/autoload/global.php, that should not contain any module specific configs (see below);
  4. /config/autoload/local.php, that contains environment specific settings also should not contain any module specific configs (see below); it should not versioned/deployed;
  5. /config/autoload/{ModuleNamespaceLowerCased}.local.php (e.g. cache.local.php), that contains only the module AND environment specific settings and should not be versioned/;

For the Cache module above there can be following config files:

  • /module/Cache/config/module.config.php -- a complete set of module configs; loaded by Cache\Module#getConfig()
  • /module/Cache/config/cache.local.php.dist -- an example for /config/autoload/cache.local.php
  • /config/autoload/cache.local.php -- environment specific module configs

The setting ttl can be accessed from any place, where one has access to the Service Locator. For example in factory methods of Cache\Module#getServiceConfig()

class Module {

    public function getConfig() {
        $moduleConfig = include __DIR__ . '/config/module.config.php';
        $application = $this->getApplicationSomehow(); // <-- how?
        $applicationModuleConfig = $application->getConfig()['modules'][__NAMESPACE__];
        $config = array_merge($moduleConfig, $applicationModuleConfig);
        return $config;
    }
    ...
    public function getServiceConfig() {
        try {
            return array (
                'factories' => array(
                    'Zend\Cache\Adapter\MemcachedOptions' => function ($serviceManager) {
                        return new MemcachedOptions(array(
                            'ttl'            => $serviceManager->get('Config')['ttl'],
                            ...
                        ));
                    },
                    ...
                )
            );
        }
        ...
    }
    ...
}

For futher information about how configs are managed in ZF2 see Sam's answer and blog article.