One application, multiple configurations

Published on and tagged with cakephp  configuration

Recently I had to run two instances of NoseRub, each instance using its own configuration and database. How could this be accomplished?

My first approach was to simply check out a second copy of the app folder from the repository, and to configure it differently. It worked, but it was a pain to keep the app folders synchronized…

So I searched for a better solution. As I looked for a way to load my own version of cake/config/paths.php I suddenly remembered that you can define additional paths for controllers, models, views, etc., in app/config/bootstrap.php.

In the bootstrap.php file of the second instance I then added the following lines:

$modelPaths = array('<path to first instance>/app/models/');
$viewPaths = array('<path to first instance>/app/views/');
$controllerPaths = array('<path to first instance>/app/controllers/');
$behaviorPaths = array('<path to first instance>/app/models/behaviors/');
$helperPaths = array('<path to first instance>/app/views/helpers/');
$componentPaths = array('<path to first instance>/app/controllers/components/');

Two things are important to know (and of course I didn’t knew them at that time *g*): the paths have to end with a slash (resp. the path delimiter on your system), and if you specify for example a controller path it doesn’t mean the respective components are found automatically and so you have to define the path for the components explicitly. Same for views and helpers, and models and behaviors.

A nice side effect is that the folders for controllers, models, and views are no longer needed in the app folder, so they (plus some other folders which are not used) can be removed and we get the following structure:

/app
  /config
  /tmp
  /webroot
  app_controller.php
  app_model.php

You have to experiment a bit to find the structure which works for your application. And if there is still redundant stuff (e.g. in the js folder in app/webroot), then you can create symlinks for those folders.

With this solution it is relatively easy to run your application with different configurations.

6 comments baked

  • Yevgeny Tomenko

    This solution perfect if you host both application on one server but for set of servers I preffer other:
    i use deployment tool similar to Felix deploy shell, that upload updates from svn to set of servers with posibilty of individual modifications for each server.
    This allow automate cloning.

  • cakebaker

    @Yevgeny: Thanks for your comment.

    Yes, to use this approach everything has to be on the same server. I have to admit I didn’t thought about using this approach in a live scenario when I wrote this article. I only had a development scenario in my mind, as that’s what I am using this approach for.

  • Zonium

    I tried to follow this approach, but I have a problem with vendor inclusion.
    I have a couple of classes in vendors folder in the first (master) instance. vendor() function failed to load classes in there when running the second instance.
    Do I have to specify $vendorPaths?
    Looking into the vendor() function definition in the core, I don’t see any reference to $vendorPaths.
    Any workaround?

  • cakebaker

    @Zonium: Thanks for your comment.

    There are two possible workarounds: creating a symlink, or moving the vendor classes from /app/vendors to /vendors.

    HTH

  • Zonium

    Thanks cakebacker, the second solution works (and by the way, it’s also recommended by gwoo as well). However, it seems to me this is a small design issue. It is possible to specify alternative paths for controllers, components, models, views, etc. Naturally it should be able to do the same for vendors as well.

  • cakebaker

    @Zonium: Good to hear that :)

    Yes, I agree with you, it would be more consistent if you could define a vendorsPaths variable.

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License