SitePoint Sponsor

User Tag List

Results 1 to 18 of 18
  1. #1
    SitePoint Member
    Join Date
    Jul 2007
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Arrow Application configuration, which pattern to use ?

    Hi

    I am currently stuck with the design of the configuration of a whole application.

    What i use right now is a very simple registry which is segmented by class name.
    It does look like this :

    $config['class1']['key1'] = 'sum1';
    $config['class2']['key2'] = 'sum2';
    ...

    Then i can retrieve, override by class and key with a simple method.
    For example:
    PHP Code:
    class extends class {

    public function 
    __construct()
    {
    parent::__construct();
    $this->prop $this->config('key');


    The config() method returns mixed (array| false), false when no config has been found.
    I am still thinking about throwing exception if the configuration is not found for a class .. but i don't feel like this is a good solution .

    Maybe you do have a better method for solving this problem ?

    Thanks
    Last edited by integerx00; Jul 28, 2007 at 04:52.

  2. #2
    SitePoint Addict Jasper Bekkers's Avatar
    Join Date
    May 2007
    Location
    The Netherlands
    Posts
    282
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by integerx00 View Post
    Hi
    The config() method returns mixed (array| false), false when no config has been found.
    I am still thinking about throwing exception if the configuration is not found for a class .. but i don't feel like this is a good solution .
    The simplest solution is to add a parameter to the config() method for a default value. So all calls to config() now look like $this->config('my-setting', 'default-value'). This can introduce some redundant work if you need the same setting multiple times so you could move the default values to an external file.
    Design patterns: trying to do Smalltalk in Java.
    I blog too, you know.

  3. #3
    SitePoint Evangelist
    Join Date
    Feb 2005
    Posts
    581
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't think this involves any sort of "pattern", per se. The way that I do mine is by keeping the configuration variables in a separate file and then loading them into an array that can be passed around throughout the program.

    Rough Example:
    PHP Code:
    ;settings .ini
    [section]
    key=value
    otherKey
    =otherVal
    etc 
    PHP Code:
    <?php
    // Config.class.php
    Class Config
    {
      public 
    $iniData;

      public function 
    __construct()
      {
        if (!(
    $this->iniData ini_parse_file('settings.ini'))
          throw new 
    Exception ('Settings file could not be parsed!);
      }

      public function getData()
      {
        return $this->iniData;
      }
    }
    PHP Code:
    $config = new Config();
    $data $config->getData();
    $data $config->iniData// also works 
    Keep in mind that the above is just a very basic example; my actual config files and classes are much more complex.
    I will not flame the newbies,
    I will not flame the newbies,
    I will flame the newbies...
    Table free is the way to be!

  4. #4
    SitePoint Member
    Join Date
    Jul 2007
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This can introduce some redundant work if you need the same setting multiple times so you could move the default values to an external file.
    I do understand that, in my case that will mean having 2 files for the whole configuration : one for user provided configuration, one for default critical behavior.

    Maybe i should just do an array_merge() on these files and store it in a registry.

    @BluDragon : Maybe you do load from .ini for security reasons ?

    PHP Code:
    abstract class Root {
    ...
     protected function 
    _config($key
    {
    $class get_class($this);
    return 
    App:config($class$key)
    }
    ...
    }

    class 
    App {
    ...
    public static function 
    config($class$key null
    {
     if(!
    self::$loaded) {
           
    self::_load(array(self::$default_configself::$user_config); //or something like that
    }
    if(empty(
    $key)) {
    //load whole class config
    }
    else {
    //return key of $class
    //throw exception if not found
    }
    }
    ...
    //woo i love indentation :D


    That's what i do currently, and I am still not convinced that's the best way .
    Still looking for better implementation

  5. #5
    SitePoint Evangelist
    Join Date
    Feb 2005
    Posts
    581
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was just using INI because it seemed to be the easiest example. I actually prefer to use YAML via my own custom parser.
    I will not flame the newbies,
    I will not flame the newbies,
    I will flame the newbies...
    Table free is the way to be!

  6. #6
    SitePoint Member
    Join Date
    Jul 2007
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmmm i'll stick with php arrays
    Exchanging 3000+ PR 3 to 5 links, pm me for info

  7. #7
    SitePoint Evangelist
    Join Date
    Aug 2004
    Posts
    428
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    problem

    I'm actually am actually trying to implement a configuration parser myself...

    associative arrays is a good approach for small sites.

    languages that can be compiled removing configuration data out of the compliation is a good thing... as you don't have to recompile anything after the change. example .. changing path to resources

    since php is interpreted associative arrays will work for name = value examples

    this approach falls short when you use a config file for depedency injection.
    Meaning you want to instantiate a different provider for a menu control, different caching, error handling, ..ect

    Eventually you need more information than name value approach .. u also need type...eventually you need hierachy ... so you end up with an xml file.


    asp.net sites use a web.config = xml file
    php prado uses an xml file also = application.xml

    A simple way to retrieve the value via an xml file is like prado ... getElementsByTagName ...


    My implementation is going be more like asp.net were you define sections which are associated with an object.

    as you parse a section you create the object and pass the XmlNode into the constructor to finish parsing and copying values to member variables inside the object.

    that will be my approach.

  8. #8
    SitePoint Wizard Mike Borozdin's Avatar
    Join Date
    Oct 2002
    Location
    Edinburgh, UK
    Posts
    1,743
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    leblanc,

    I got your point, but why not to use PHP as it is? If PHP is an interpreted language and can include script files on the fly which is much faster than reading an INI file, why just don't use it? You can still wrap it into any pattern you like. You deal with a certain language (PHP), not with an abstract language.

  9. #9
    SitePoint Member
    Join Date
    Jul 2007
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi guys

    I did it this way

    PHP Code:

    class FR_Root{

        

        public function 
    __construct()
        {
            
    //push default configuration of this instance in static FR::$_config
            
    FR::addConfig($this->_defaultsget_class($this));

        }

        
    /**
         * Shortcut method for retrieving configuration of class
         *
         * @param string $key Key for the classname segment
         * @param string $class Optional, gives access to any class configuration
         * @return array The array config for the class
         */
        
    public function config($key$class null)
        {
            
    $class get_class($this);
            return 
    FR::getConfig($class$key);
        }

    //continues


    ...
    }


    Class 
    AClassThatCanBeUserConfigured extends FR_Root {

    //were defaults is the minimal programmatic configuration for this class
    protected $_defaults = array('key' => 'value''key' => array(), ...);

    public function 
    __construct()
    {
    parent::__construct();

    $this->prop $this->getConfig('key1');
    $this->prop2 $this->getConfig('key3');
    }

    }

    class 
    FR {

    /**
         * Application configuration. Registry pattern, supports push and get.
         * Configuration is segmented by class name.
         *
         * @var array
         */
        
    protected static $_config = array();




        protected static function 
    _initEnvironment()
        {
            
    //--cut

            //add defaults
            
    self::addConfig(self::$_defaults'FR');
            
    //override with user provided
            
    self::_fetchConfig();

            
    //--cut

        
    }

    /**
         * Configuration getter. Get by classname and key
         *
         * @param string $class The classname
         * @param string $key Array key of classname
         * @return mixed Mainly array, secondly strings
         */
        
    public static function getConfig($class null$key null)
        {
            if(empty(
    $class)) {
                return 
    self::$_config;
            }

            
    //looking for a class config ?
            
    if(empty($key)) {
                if(
    array_key_exists($classself::$_config)) {
                    return (array) 
    self::$_config[$class];
                }
            } else {
                
    //looking for an element
                
    if(array_key_exists($keyself::$_config[$class])) {
                    return 
    self::$_config[$class][$key];
                }
            }

            
    //never found
            
    throw new Exception("Config for ': $class: ' & ': $key: ' not found");

        }

    /**
         * Add default configuration to FR::$_config, or single element
         * User provided configuration has priority over defaults. (config > class props)
         * Runtime controllers can override user provided settings
         *
         *
         * 
         * @param string $class The classname to find the config array
         * @param string $key The key for that classname
         * @param mixed $add Configuration array or element to push in current config
         * 
         * @return void
         * 
         * @todo Speed test
         */
        
    public static function addConfig($add $class$key null)
        {

            if(
    array_key_exists($classself::$_config)) {
                foreach((array) 
    $add as $ukey => $uval) {
                    if(empty(
    self::$_config[$class][$ukey])) {
                        
    self::$_config[$class][$ukey] = $uval;
                    }
                }
            } else {
                
    self::$_config[$class] = (array) $add;
            }
        }
    }

    //And the config file
    $config['Class']['prop'] = 'string';
    $config['Class']['dependency_object'] = FR::reference('class_name');

    $config['Class_Z']['key'] = '..'

    //pretty much anything can be found here 
    This way i got fine grained configuration for each class of the framework, i really dont understand why i should switch to XML or anything else.

    Maybe you do have an example or you can tell me in which cases this implementation will fail ?
    Exchanging 3000+ PR 3 to 5 links, pm me for info

  10. #10
    SitePoint Evangelist
    Join Date
    Aug 2004
    Posts
    428
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    you need objects as you can host multiple values for a single entity.

    http://www.sitepoint.com/article/web...le-demystified

  11. #11
    SitePoint Member
    Join Date
    Jul 2007
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The configuration segmentation is done for each class, and within each class unique keys stores mixed values.

    I have read the article, and it is clear that I don't have the same approach. Instead of giving a very detailed configuration file to users that can manage everything within the application, I just give them a way to modify a limited set of properties per classes.

    For example the ACL, is not stored in the configuration file. As a consequence
    user provided config files cannot modify the main behavior of the application. There is public methods for that ...

    You are indeed right about the fact that this approach can't fit *really* huge project. I've never come accross this kind of project yet.
    Exchanging 3000+ PR 3 to 5 links, pm me for info

  12. #12
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am in the process of building-in configuration methods myself, and currently have all my configuration based in and extended by individual classes, much like the code integerx00 has posted. This is mostly due to the goal of my framework, that each component (or "module") should also be able to serve its function independent of the framework, and should be fully self-contained. That is, all files and configurations for each component are stored with the component so they can be moved around freely from project to project without moving anything else. It's serving my needs well, and has very low overhead as it's all in PHP. Why waste all that overhead parsing a file, when as other people in this thread have stated, PHP is an interpreted language?

  13. #13
    SitePoint Evangelist
    Join Date
    Aug 2004
    Posts
    428
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    read

    >Why waste all that overhead parsing a file, when as other people in this thread >have stated, PHP is an interpreted language?

    dependency injection.
    Helps decouple providers from the goal of your application!!!

    you can inject a new provider that handles authentication - winforms, passport, ..., categories - preorder,adjacency,basic, menus - horizontal, vertical, with datasource as xml sitemap or a db sitemap.

    you can even inject intercept filters.... called services in prado and called httpmodules in asp.net.

    make all these changes... without having to dig in your code.

    of course the framework must then be designed to use the Iinterface instead of working with a specific provider.

  14. #14
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by leblanc View Post
    you can inject a new provider that handles authentication - winforms, passport, ..., categories - preorder,adjacency,basic, menus - horizontal, vertical, with datasource as xml sitemap or a db sitemap.

    you can even inject intercept filters.... called services in prado and called httpmodules in asp.net.

    make all these changes... without having to dig in your code.

    of course the framework must then be designed to use the Iinterface instead of working with a specific provider.
    You can still do all of these things using a PHP file...

  15. #15
    From space with love silver trophy
    SpacePhoenix's Avatar
    Join Date
    May 2007
    Location
    Poole, UK
    Posts
    5,077
    Mentioned
    103 Post(s)
    Tagged
    0 Thread(s)
    bring this back on topic, an array method that i have seen used is:


    "setting group" => array(
    "setting" => "value",
    ),

    i don't know for sure if it would make the values available to all objects (global scope).

  16. #16
    SitePoint Member
    Join Date
    Jul 2007
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @leblanc You are right about the fact that, I need to dig into the code quite often.

    I am afraid i can't handle such a configuration system (interfaces, adapters) , i think i'll get there step by step

    There I also get why you need a facility language to write the configuration file, but doing it in arrays is still good.

    Thanx for the clarification
    Exchanging 3000+ PR 3 to 5 links, pm me for info

  17. #17
    SitePoint Guru
    Join Date
    Jul 2004
    Location
    Netherlands
    Posts
    672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Umm why not use constants ?
    Go visit my site :-D you know you want to ;-)
    www.mech7.net

  18. #18
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Manchester, UK
    Posts
    83
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi All,

    Heres an Interesting article form IBM Developerworks about PHP Configuration Patterns:

    http://www.ibm.com/developerworks/li...fig/index.html


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •