ZF2 config caching with Composer
I recently stumbled upon a couple of config options within the Zend Framework 2 Skeleton Application, in the ./config/application.config.php file that relate to config caching. The options are:
<?php
return array(
// These are various options for the listeners attached to the ModuleManager
'module_listener_options' => array(
// 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,
// The path in which to cache merged configuration.
'cache_dir' => $stringPath,
),
);
First, some background: ZF2 uses multiple config files which it merges together at run-time to build the application config. This allows you to keep your config broken up into different logical components, and provides an easy way to have environment-specific (local) config files. However, this also increases resource usage and lowers performance, since it needs to read multiple files and merge multiple complex arrays each time it runs the application.
Luckily, the options I stumbled upon are designed to help! Enabling the config caching options tells the application to save the merged config in a cache file. This replaces multiple file reads, and lots of processing, with a single file read. Enabling caching is a simple matter of setting config\_cache\_enabled to true, and specifying config\_cache\_key and cache_dir.
For example:
<?php
return array(
// These are various options for the listeners attached to the ModuleManager
'module_listener_options' => array(
// Whether or not to enable a configuration cache.
// If enabled, the merged configuration will be cached and used in
// subsequent requests.
'config_cache_enabled' => true,
// The key used to create the configuration cache file name.
'config_cache_key' => 'my_project',
// The path in which to cache merged configuration.
'cache_dir' => __dir__ .'/../data/cache',
),
);
However, there is a catch… Since it is caching the config files, any time you make changes to the config you need to remove the cache file before the application will notice it. During production this isn’t too much of a problem, since you can remember to clear the cache when you roll out a new version, but during development it’s quite annoying. Now, ZF2 comes with the facility to manage local and global config, but this doesn’t apply to the ./config/application.config.php file, which is global by default, and leaves with you with having to remember to edit the config file in production (or development)… Which is something a lazy/busy developer doesn’t really want to have to remember.
So, the problem we face is that we can enable config caching easily, but as an all-or-nothing option. Is there a way to automatically enable it for production (and clear the cache whenever we perform a code update), but leave it disabled in development?
With the help of our good friend Composer: YES!
Composer has a fantastic scripts option that can be set within your application’s composer.json file. We can use this, and a little sed magic, to automatically toggle caching on and off depending on us being in production and development mode. A basic example looks like this:
{
"scripts": {
"post-install-cmd": [
"sed -i \"s/'config_cache_enabled' => false,/'config_cache_enabled' => true,/g\" ./config/application.config.php",
"rm -f ./data/cache/module-config-cache.my_project.php"
],
"post-update-cmd": [
"sed -i \"s/'config_cache_enabled' => true,/'config_cache_enabled' => false,/g\" ./config/application.config.php",
"rm -f ./data/cache/module-config-cache.my_project.php"
]
}
}
Let’s break it down:
post-install-cmd tells composer what commands to run after a successful execution of composer.phar install. Since you generally run this command when you install, and update, a production application, it will trigger the two commands in production. The first command uses sed to replace 'config_cache_enabled' => false, with 'config_cache_enabled' => true, within the application config, which as you should be able to tell will enable caching. The second command will remove any existing config cache file, to ensure a fresh version of the config is cached on the next page load.
post-update-cmd tells composer what commands to run after a successful execution of composer.phar update. This command is generally run on a development installation, since you usually want the latest and greatest dependencies for testing and dev. This does the opposite of the post-install-cmd, i.e. it disables the cache setting and removes the cache file just in case one exists.
To get all this working together, I configure the cache options but leave it disabled in git and have the scripts configured in my composer.json. This means that any time it changes in development, a quick git status will let me know, and as each time I roll out updates in production I also run composer.phar install, it will automatically be enabled.
That’s basically it
With a very small amount of setup, you now have config caching automatically enabling and disabling in ZF2 via Composer.