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?
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!
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 ServiceManager
and access your configs with $serviceManager->get('config');
. (see Sam's comment)
The loading order of the configs is by default:
/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')
).
{ModuleNamespace}\Module#getConfig()
(e.g. Cache\Module#getConfig()
), that by convention should load its /module/{ModuleNamespace}/config/module.config.php
;
/config/autoload/global.php
, that should not contain any module specific configs (see below);
/config/autoload/local.php
, that contains environment specific settings also should not contain any module specific configs (see below); it should not versioned/deployed;
/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.