Jul 182012
 

So you’re all excited to try out ZF2. You clone the skeleton, install some modules, maybe even follow Rob Allen’s excellent ZF2 tutorial, and finally, start building your application. Now, if you’re a former ZF1 user or refugee from another framework, you might be troubled at this point by the fact that, at first glance, ZF2 doesn’t appear to take into consideration environment-specific configuration values (e.g., development, testing, staging, production). Luckily, this is not the case!

The ZF2 way (recommended)

The officially sanctioned “ZF2 way” is a notion of “local” config files. That is, if a specific environment needs a different config value for something, you put that in a local config file in that environment. By convention, these local config files are ignored from source code control. This practice helps discourage committing sensitive information like database credentials into source code control, however it leaves deployment of these “local” configuration files up to the user and their particular deployment process.

Personally, for each local config file I have for my application, I commit a .dist variant of it into source code control, with any sensitive values removed. Then the deployment task is simply to copy the dist files and populate the appropriate values for each environment, or in some cases the dist files can even have the values for a specific environment already enabled (granted they don’t pose a security risk!). For example I might have a ./config/autoload/logger.local.php.dist-testing file which sets a null logger, with a post-receive hook on the testing server or before_install task on travis-ci that copies the file without the .dist-testing extension. So far, this practice has been working quite well for me.

The ZF1 way (for those stuck in the past)

However, if the whole “local” config file thing just isn’t sitting right with you, it’s extremely simple to get that old behavior back. Open up your config/application.config.php file and add an additional glob path (line 9):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
return array(
    'modules' => array(
        'Application',
    ),
    'module_listener_options' => array(
        'config_glob_paths'    => array(
            'config/autoload/{,*.}{global,local}.php',
            'config/autoload/{,*.}' . (getenv('APPLICATION_ENV') ?: 'production') . '.php',
        ),
        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
);

Note: In the above example, I have set ‘production’ as the default environment if no APPLICATION_ENV variable is set. You can of course change this, though it’s generally best practice to assume production for the off chance that the environment variable somehow becomes undefined in your production environment.

You can now add config files such as ./config/autoload/logger.staging.php, which will only be loaded on the server with the APPLICATION_ENV environment variable set to ‘staging’. This gives you that familiar functionality that config/ini sections gave you in ZF1.

Enjoy, and please remember not to commit sensitive information like database credentials into source control!

  7 Responses to “Environment-specific configuration in Zend Framework 2”

  1. Thank, this is what i was looking for.

    But, how can we achieve inheritance?

    • Read the article: “Then the deployment task is simply to copy the dist files and populate the appropriate values for each environment, or in some cases the dist files can even have the values for a specific environment already enabled (granted they don’t pose a security risk!). For example I might have a ./config/autoload/logger.local.php.dist-testing file which sets a null logger, with a post-receive hook on the testing server or before_install task on travis-ci that copies the file without the .dist-testing extension.”

      The point is that because ZF2 globs config files, you can set the precedence by which they are loaded. Typically, you should only be concerned with global settings and ones specific for the current environment — the latter can be in .dist files if they absolutely must be, but they can also be in another directory entirely, which you add to the glob patterns. This allows you to inherit easily, and have per-environment settings.

  2. What is the best way to read those config values from either a Model or a Controller?

  3. Hi Evan,

    Very clean and usefull post, thanks! I translate it to Russian and post on my blog about ZF, if you don’t mind.

  4. How about the application.config.php?

    I’m trying to load up the “ZendDeveloperTools” and “BjyProfiler” modules only at development and I’d be happy to do it without the environment variable. Any ideas?

  5. This is great & perhaps I’m missing something, but the thing that I miss most about the environment variables from ZF1 is that the dev environment had error reporting set to E_ALL, which seems to be turned off somewhere in the Zend\Application class.

    I found this workaround

    http://www.thisprogrammingthing.com/2012/enabling-error-displays-in-zend-framework-2/

    But I’m wondering if this should be the accepted way to do it?

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre user="" computer="" color="" escaped="">