configuration | Dmytro Shteflyuk's Home https://kpumuk.info In my blog I'll try to describe about interesting technologies, my discovery in IT and some useful things about programming. Tue, 08 Sep 2015 00:34:39 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 Flexible application configuration in Ruby on Rails https://kpumuk.info/ruby-on-rails/flexible-application-configuration-in-ruby-on-rails/ https://kpumuk.info/ruby-on-rails/flexible-application-configuration-in-ruby-on-rails/#comments Sat, 14 Oct 2006 04:27:48 +0000 http://kpumuk.info/ruby-on-rails/flexible-application-configuration-in-ruby-on-rails/ In my current project based on Ruby on Rails framework, I need to store application specific configuration somehow. There are several approaches I’ve found in Internet: AppConfig plugin, several methods described on the HowtoAddYourOwnConfigInfo wiki page, but neither one looks “config-like”. Me with my friend, Alexey Kovyrin, discovered all of them and decided to use […]

The post Flexible application configuration in Ruby on Rails first appeared on Dmytro Shteflyuk's Home.]]>
In my current project based on Ruby on Rails framework, I need to store application specific configuration somehow. There are several approaches I’ve found in Internet: AppConfig plugin, several methods described on the HowtoAddYourOwnConfigInfo wiki page, but neither one looks “config-like”. Me with my friend, Alexey Kovyrin, discovered all of them and decided to use YAML-file as a configuration format. In my opinion, the ideal configuration file looks like this:

1
2
3
4
5
6
7
8
9
10
11
common:
  support_email
: [email protected]
  root_url
: myhost.com
  photos_max_number
: 6

production
:
  email_exceptions
: true

development
:
  root_url
: localhost:3000
  photos_max_number
: 10

In this example you can see three sections: common will be used as a base configuration for all environments, production and development — environment specific options. Optional sections are production, development, and testing, or any other custom environment name. I’ve placed this file in config/config.yml and created lib/app_config.rb which looks like this:

1
2
3
4
5
6
7
8
# Load application configuration
require 'ostruct'
require 'yaml'
 
config = YAML.load_file("#{Rails.root}/config/config.yml") || {}
app_config = config['common'] || {}
app_config.update(config[Rails.env] || {})
AppConfig = OpenStruct.new(app_config)

Now I’m able to use constructions like AppConfig.support_email and AppConfig.root_url. Looks like I’ve kept all my configs as DRY as possible :-)

The post Flexible application configuration in Ruby on Rails first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/ruby-on-rails/flexible-application-configuration-in-ruby-on-rails/feed/ 16
Zend Framework: Thoughts about Zend_Config https://kpumuk.info/php/zend-framework-thoughts-about-zend_config/ https://kpumuk.info/php/zend-framework-thoughts-about-zend_config/#comments Fri, 10 Mar 2006 08:48:44 +0000 http://kpumuk.info/php/zend-framework-thoughts-about-zend_config/ In Zend Framework’s mailing list discussion about Zend_Config class is in full swing. I have my own ideas about this class and I will try to explain their here. I need something that can load and save configuration into different storages (for example, XML, database or plain text like INI-files), it’s necessary to have ability […]

The post Zend Framework: Thoughts about Zend_Config first appeared on Dmytro Shteflyuk's Home.]]>
In Zend Framework’s mailing list discussion about Zend_Config class is in full swing. I have my own ideas about this class and I will try to explain their here. I need something that can load and save configuration into different storages (for example, XML, database or plain text like INI-files), it’s necessary to have ability to change every parameter of storage (for example, file name, database tables or even database structure), it will be able if I can extend storage system with my own storage strategies.

First I’ll try to imagine how user’s code will look:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Zend::loadClass('Config');

// Use default XML-persistence engine
$config = new Config('config.xml');

// Use plain text storage engine
Zend::loadClass('Config_Text_Storage');
$persistance = new Config_Text_Persistance('config.ini');
$config->setPersistance($persistance);

echo 'Host: ' . $config->database->host->value . '<br/>';
echo 'Port: ' . $config->database->host->port . '<br/>';
echo 'Database: ' . $config->database->name . '<br/>';
echo 'User: ' . $config->database->user . '<br/>';
echo 'Password: ' . $config->database->password . '<br/>';

I think configuration representation in memory will be objects tree. Config will be user friendly class with several simple functions like load, save configuration, change persistance engine, access root node of configuration object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/** Exception for Config class. */
require_once 'Config/Exception.php';

/** Exception for Config class. */
require_once 'Config/Persistance/Interface.php';

class Config
{
  private $_persistance = null;

  private $_rootNode = null;

  /**
   * Create configuration object. You can pass string argument with
   * path to XML configuration file.
   *
   * @param string $xmlConfigPath
   */

  public function __construct($xmlConfigPath = null)
  {
    require_once 'Config/XML/Persistance.php';
    $this->_persistance = new Config_XML_Persistance($xmlConfigPath);

    if ($xmlConfigPath) $this->load();
  }

  /** Save configuration. */
  public function save()
  {
    $this->checkPersistanceAssigned();
    $this->_persistance->save();
  }

  /** Load configuration */
  public function load()
  {
    $this->checkPersistanceAssigned();
    $this->_persistance->load();
    $this->_rootNode = $this->_persistance->getRootNode();
  }

  /**
   * Get config variable with $name name.
   *
   * @param string $name
   * @return mixed
   */

  public function __get($name)
  {
    return $this->_rootNode->__get($name);
  }

  /**
   * Set persistance object.
   *
   * @param Config_Persistance_Interface $persistance
   */

  public function setPersistance(Config_Persistance_Interface $persistance)
  {
    $this->_persistance = $persistance;
  }

  /** Check if persistance object has been assigned. */
  private function checkPersistanceAssigned()
  {
    if (!$this->_persistance) throw new Config_Exception('No configuration persistance object assigned');
  }
}

Configuration nodes are very easy to code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

class Config_Node
{
  private $_values;

  public function __construct($root = null)
  {
    $this->_values = $root;
  }

  public function __get($name)
  {
    if (array_key_exists($name, $this->_values) === false)
      throw new Config_Exception('No config node "' . $name . '" defined.');

    if (is_object($this->_values[$name])
      && sizeof($this->_values[$name]->_values) == 1
      && array_key_exists('value', $this->_values[$name]->_values))
    {
      return $this->_values[$name]->__get('value');
    }

    return $this->_values[$name];
  }

  public function __set($name, $value)
  {
    $this->_values[$name] = $value;
  }
}

Now I’ll try to develop simplest strategy for XML-based storage.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/** Exception for Config_XML_Persistance class. */
require_once 'Config/XML/Exception.php';

/** Interface Config_Persistance_Interface. */
require_once 'Config/Persistance/Interface.php';

/** Configuration node class Config_Node. */
require_once 'Config/Node.php';

class Config_XML_Persistance implements Config_Persistance_Interface
{
  private $_xmlConfigFile = null;
  private $_rootNode = null;

  public function __construct($xmlConfigFile = null)
  {
    $this->_xmlConfigFile = $xmlConfigFile;
  }

  /** Load configuration from XML file. */
  public function load()
  {
    if (!$this->_xmlConfigFile)
      throw new Config_XML_Exception('Config file name is not assigned.');

    $dom = new DOMDocument();
    $dom->preserveWhiteSpace = false;
    $dom->load($this->_xmlConfigFile);

    $this->_rootNode = $this->populateConfig($dom->documentElement);
  }

  /** Save configuration to XML file. */
  public function save()
  {
    throw new Config_XML_Exception('save() function is not implemented for this persistance type.');
  }

  /** Returns root configuration node. */
  public function getRootNode()
  {
    return $this->_rootNode;
  }

  /**
   * Read nodes starting from $root and fill Config_Node objects.
   * Returns root Config_Node object.
   *
   * @param DomNode $root
   * @return Config_Node
   */

  private function populateConfig($root)
  {
    $configNode = new Config_Node();
    foreach ($root->attributes as $attribute)
      $configNode->__set($attribute->name, $attribute->nodeValue);

    foreach ($root->childNodes as $node)
    {
      if ($node->nodeType === 1)
        $configNode->__set($node->tagName, $this->populateConfig($node));
      else
        $configNode->__set('value', $node->nodeValue);
    }
    return $configNode;
  }
}

Here simple configuration XML-file:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>

<config>
  <database type="mysql">
    <host port="3306">localhost</host>
    <name>test</name>
    <user>root</user>
    <password>123456</password>
  </database>
</config>

You can see one obscure aspect of the configuration node class. Please look at host node of configuration: we have an attribure and text node in it. What about ambiguity? How we can access text node? We can’t do following:

1
2
$host = $config->database->host;
$host = $config->database->host->port;

My solution for this problem is pseudo-variable value:

1
2
$host = $config->database->host->value;
$host = $config->database->host->port;

If there are no attributes, pseudo-variable value will be used by default.

You can download my configuration classes here.

The post Zend Framework: Thoughts about Zend_Config first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/zend-framework-thoughts-about-zend_config/feed/ 5