views:

259

answers:

4

I'm building an MVC framework in PHP that will need to set a number of default configuration variables/constants. Example config vars would be where to save log files, whether to log queries, Doctrine settings, amongst many others. Because I want developers to be able to create new projects with minimal fuss, these config vars should have default values. However to make this framework truly useful, I need them to be able to override these default values either in a project bootstrap file, or from within a controller or model. I would love to use constants, but they cannot be overwritten. I feel as though there must be a simple solution that I just don't see (perhaps a design pattern?). Any advice would be greatly appreciated, thanks.

A: 

Here's the design pattern I would use. I would create a simple class to facilitate it:

class Configuration {
   String get($key) {...}
   String set($key, $value) {...}
}

Initial implementation could all be hard-coded with default values. Later, though, you could slip in the reading of a server and/or project specific configuration file. It would give you flexibility to add as needed.

(I also noticed that the php.ini configurations seem to have the behavior you want, but I don't see how you leverage that system directly.)

ndp
shouldn't it be `void set(...)` or do you return the old value?
nickf
+3  A: 

In a situation like this, I would probably :

  • Create a class that deal with everything configuration-related
    • That class would contain methods to get/set configurations options ; whatever your application needs
    • It would also define default values, when suitable
  • Use a .ini or .xml file, in which configuration values can be re-defined

When instanciating the class :

  • You already have the default values
  • You parse the .ini or .xml file
  • Each value defined in that configuration file is used to override the corresponding default value that what defined in the class.


A solution a bit more complex, but maybe better, might be to :

  • Still have that configuration class, but not use it to store any default values
  • Have one .ini or .xml file to store default values
  • Have one .ini or .xml file in which people can override the values defined in the default one
  • Load the file containing the default values, and then the one containing the specific ones

Advantages of this solution are :

  • No configuration value stored in a PHP class
  • All configuration options that can be overriden are already defined in a .ini / .xml file, which means people just have to copy/paste a line to their specific file to override : no need to go take a look at the PHP class and think "how do I translate this to a config file ?"


A couple more notes :

  • You might want to use some kind of caching-mecanism, to not re-parse the files at each request
  • Zend_Config and Zend_Config_Ini might be helpful ; even if you don't use those, as you are writing your own framework, you might want to take a look at what they do -- If I remember correctly, Zend_Config_Ini allows for hierarchy and inheritance in .ini files

Have fun!

Pascal MARTIN
Thanks for the great response! I have a followup question for you: could you provide a little more info about possible caching-mechanisms? I certainly don't want to waste resources by re-parsing the files.
Arms
Hi. You're welcome :-) About caching : first rule is you shouldn't care about that right now ; wait until your application works. Then, if that's necessary, you could store the parsed configuration data in either a file, or memory (with APC or memcache, for instance) ;; just remember that you'll have to check if the config file has been modified, to know when to invalidate the cache, so the modifications are taken into account. for a bit more info, you can read the introduction of http://framework.zend.com/manual/en/zend.cache.frontends.html#zend.cache.frontends.file (even if you don't use ZF)
Pascal MARTIN
+1  A: 

I'd suggest using several ini files: a default.ini, and then as much override.ini-s as you need. Then simply load them with parse_ini_file() and merge into one config with array_merge(). Quick and simple.

n1313
A: 

This question can come with a wide variety of answers. My personal recomendation would be to store values into SQLite and have a seperate script to access and change those values. For other way continue to read.

This is pretty simple depending on how object oriented you want to be and how simplified you want to make things for your users. Your install instructions could simply instruct users to edit a file directly. In which case you could simply instruct users to edit a file of constants directly.

Most applications that follow this route implement it with detail explination

<?php
/**
 * Global application configuration
 */
class AWConfig {

    /**
     * true or false
     * If the is set to true debug messages will be added to the application logs
     */
    public $DEBUG_MODE = true;
    /**
     * Path to Station database
     * ex (/homepages/26/3/htdocs/databases/stations.db)
     */
    public $DB_STATION = '/homepages/26/3/htdocs/databases/stations.db';
    /**
     * Path to logs database
     * ex (/homepages/26/3/htdocs/databases/stations.db)
     */
    public $DB_LOGS = '/homepages/26/d175338743/htdocs/weather/dev/metrics/beta2/databases/metriclogs.db';

    /**** DO NOT EDIT BELOW THIS LINE *****/
    public $LIST_STATION_LIMIT = 10;
    public $MAX_COMPARE = 6;
}
?>

If you want to hide these details from the user than an initial setup script would be best that would prompt user for details and write a file (config.php, config.ini, config.xml, or to a database) the settings they chose. Then a different script to edit in the future. Good example would be Joomla CMS.

Cody N