How to use the global.php/local.php configs in the getConfig() of a module in a Zend Framework 2 application?
Solution 1
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 byCache\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.
Solution 2
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 yourttl
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!
automatix
Updated on June 05, 2022Comments
-
automatix almost 2 years
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 theModule
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? -
automatix about 11 yearsOK, I think, I got the logic.
local.%module%.php.dist
(an example forlocal.%module%.php
) andmodule.config.php
(default settings) in/module/Cache/config
andlocal.%module%.php
(real settings for the current environment) in/config/autoload
.local.%module%.php
files are merged "automatically" (magic?) to the/config/autoload/local.php
and has a higher prioroty thanmodule.config.php
. 1. Do I understand this right? 2. What about the keys? If thelocal.%module%.php
files are directly merged tolocal.php
, how are conflicts avoided? 3. How can/should I access the settings? -
automatix about 11 yearsAt Sam: Thank you very much for your detailed answer and the update. Sorry, I still cannot understand, how to load the
/autoload/local.{modulename}.php
files. I've created/autoload/local.cache.php
for my moduleCache
, but it is not loaded. Can you please post an elementary example, how you would set the settingmysetting
(in all possible relevant files in the module and application config folder) for a moduleMyModule
and how you would access this setting from your module class? -
automatix about 11 years@Sam To "If i understand this part of the
ConfigListener
correctly [...]": I've just debugged a module simply setting a breakpoint into each of its config methods (this module implements only three config interfaces). The loading order is:getAutoloaderConfig()
,getConfig()
,getServiceConfig()
. -
Sam about 11 years@automatix I know, just today i've blogged about my findings from here;) samminds.com/2013/04/understanding-zf2-configuration
-
automatix about 11 yearsHow do you call the settings? I'm currently doing this with
$mySetting = $this->getConfig()['mySetting']
and it cannot work, since thegetConfig()
just returns the configs from{module root directory} . '/config/module.config.php'
. -
Sam about 11 yearsI feel like you gotta provide ALL your code on github or so. What's
$this->getConfig()
? The global configuration will be fetched from the ServiceManager (i.e. inside a controller via$this->getServiceLocator()->get('config');
or iirc what you need would be$serviceManager->get('config')
-
automatix about 11 yearsI just wanted to understand, how to use settings in
MyModule#getConfig()
(and other places, where I cannot access the ServiceLocator). Yes, I can access the settings over$serviceManager->get('Config')['myConfig']
. But I don't have the access to the ServiceLocator from everywhere. E.g. fromMyModule#getConfig()
or a table mapper class or so. -
Sam about 11 yearsYou'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 onModule#getServiceConfig()
and inside the factories you do have access to theServiceManager
-
Marcel Djaman almost 9 yearsWhy u did not accept @sam answer as valid answer to your question?
-
automatix almost 9 yearsIt's a very good theoretical article (+1 for it), but it didn't give me directly the answer to my question. Anyway it helped me to understand, how configs work, and to find an answer. I posted it here and accepted / marked as "valid answer".