Handling configuration file with PHP
During development i searched an easy way to handle configuration files, either via manual editing or via interface.
At first i was using parse_ini_file() but it becomes quickly clear that i was not made to handle complex data structure.
After some readings i finally end up using var_export() to handle my configuration files.
Note that var_export() also work with objects, but you need first to implement _set_state() which can be quickly painful, especially if your object link to other objects as everyone must have a _set_state() method, so in this example i will stay only with array.
The function var_export()
The goal of var_export() is to return a parsable string representation of a variable, in clear, it return valid PHP code.
1 |
mixed var_export ( mixed $expression [, bool $return = false ] ) |
It output immediately $expression in PHP code if $return is set to false, or return it as a string if $return is set to true.
What we want is to write our configuration array into a PHP file, so we will use it with $return at true, otherwise you can use ob_start() and ob_get_contents().
Here our configuration file example :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php return array ( 'connection_timeout' => '3', 'storage' => 'SQLite', 'clusters' => array ( 'production_cluster' => array ( 0 => '127.0.1.1:11211', 1 => '127.0.1.2:11211', 2 => '127.0.1.3:11211', ), 'integration_cluster' => array ( 0 => '128.0.1.1:11211', 1 => '128.0.1.2:11211', 2 => '128.0.1.2:11211', ), ), ); |
To include it and use it, we only have to require it, it will use PHP include_path to do so.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * Load and return configuration file of path $path * * @param string $path Configuration file path * * @return array */ function load($path) { return require $path; } # Now we can use our configuration as an array ... $myConf = load('Config/file.php'); |
We can go even further by adding an environment variable (dev, prod, …) to it to handle and load the right configuration for the right place.
After load, we can implement all things that are needed to use and edit this configuration.
To save it as a PHP file, we must add a php open brace, the return instruction and a ; after the array for this instruction.
All the PHP code returned will be well formatted by var_export() to keep reading easy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/** * Save configuration array $array to path $path * Return true if successful, false otherwise * * @param string $path Configuration file path * @param string $array Configuration array * * @return boolean */ function save($path, $array) { $content = '<!--?php' . PHP_EOL . 'return ' . var_export($array, true) . ';'; return is_numeric(file_put_contents($path, $content)); } # Saving configuration save('Config/file.php', $myModifiedConf);</pre> <p>Now we can load and save one configuration file, how about doing some <strong>array_merge()</strong> to load base configuration file, and an user redefined configuration file.</p> <h3>Why not using serialize() or json_encode() ?</h3> <p>Both serialize() and unserialize are faster than json_encode() / json_decode() and json functions are not made for this.<br ?--> Even if it could be a good option, serialized content look likes a big line with a lot of number to most developer and manual editing is a bit tricky, since you must count length of each items, and modify the s:, a: in consequence. |
1 |
a:3:{s:18:"connection_timeout";s:1:"3";s:7:"storage";s:6:"SQLite";s:8:"clusters";a:2:{s:18:"production_cluster";a:3:{i:0;s:15:"127.0.1.1:11211";i:1;s:15:"127.0.1.2:11211";i:2;s:15:"127.0.1.3:11211";}s:19:"integration_cluster";a:3:{i:0;s:15:"128.0.1.1:11211";i:1;s:15:"128.0.1.2:11211";i:2;s:15:"128.0.1.2:11211";}}} |
So I will stick with var_export() for the moment as it keep the configuration code clean and easy editable.