Reputation: 679
I've been searching and reading a lot about how is the best way (code-wise) to get application's config variables in a PHP environment. After that I've sum up that are two more generally used ways to manage with configuration files and variables.
But I'm a bit confused about it, one, method 1, is using an static class. The other one, method 2 is using an instantiable class.
First one is worse to unit testing than second one. And It's similar to a global variable. Isn't it?
Second one need a global varaible in order to use instantiated object.
I'll try to explain myself.
Facts: - App's settings are kept on a INI file. - This INI file has sections, in order to maintain configuration variables. - I've got only one INI file. - Class do some validation of configuration file. - Code examples below aren't complete, it's only a sample to ilustrate my question.
This method use a Config static class, it uses static because only one Config object would be used in all application.
Code example:
class Config
{
static private $data;
static public function load($configFile) {
self::$data = parse_ini_file($configFile, true, INI_SCANNER_RAW)
}
static public get($key) {
// code stuff to deal with sections and keys, but basically
return self::$data[$key];
}
}
On my application I create the static object, once, using this code:
\Config::load('/where/is/my/ini/file.ini');
In this case, every time i want to get a value i use:
$host = \Config::get('database.host');
function example()
{
echo \Config::get('another.value');
}
In this scenario I use a Config class object.
Code example:
class Config {
private $data = array();
public function __construct($configFile) {
$this->data = parse_ini_file($configFile, true, INI_SCANNER_RAW)
}
public function get($key) {
// code stuff to deal with sections and keys, but basically
return $this->data[$key];
}
public function __get($key) {
return $this->get($key);
}
}
To use it, first we need to instantiate an object and then get the value:
$settings = new \Config('/where/is/my/ini/file.ini');
$host = $settings->get('database.host');
echo $settings->database->host;
But when I need this value inside a function, I need to use a global variable, which I think isn't right at all:
global $settings;
$settings = new \Config('/where/is/my/ini/file.ini');
function example()
{
global $settings;
echo $settings->get('another.value');
}
What I miss leading?
Thanks in advance to read and answer my question.
Upvotes: 2
Views: 2864
Reputation: 146269
Simply you may also use a php
file to keep your configurations for example, config.php
and then you may use require
from anywhere to get it:
// config.php
<?php
return array(
'database' => 'mysql',
'pagination' => array(
'per_page' => 10
)
);
Then use:
$config = require "path/to/config.php";
print_r($config);
You may use this with a function too, for example:
function someFunc()
{
$config = require "path/to/config.php";
// Now use it
}
You may create a class to get the the configurations using a method like, for example:
class Config {
static function get()
{
$config = require "path/to/config.php";
return $config;
}
}
So you may use:
$config = Config::get();
This is just another simple idea, you may extend it to use it like:
$perPage = Config::get('pagination.per_page');
Just need to add some more code to make it working like this way, give it a try.
Btw, I built a package named IConfig for my own MVC Framework
back in 2013
, it's also available on Packagist. You may use it or check it's source code, maybe you'll get better idea and can build a better one. But probably there are a lot better ones available on the web as well.
Upvotes: 5
Reputation: 1531
I think the problem you're trying to solve isn't really specific to PHP and either of the two techniques you've described could be viable ways to handle global configurations.
Having said that, I agree with Rangad, the solution is to use Dependency Injection. At it's simplest this pattern just means passing dependency's to a class/object/function as arguments. For example,
class Thing () {
private $host = '';
function __contructor($host) {
$this->host = $host;
}
function getHost()
{
echo $this->host;
}
}
$thing = new Thing( Config::get('database.host') );
$thing->getHost();
$thing2 = new Thing (Config::get('someOtherDatabase.host') );
$thing2.getHost();
This encapsulates your classes. Now they can be used in tests or even other applications so long as the needed dependences can be provided.
The nice thing about this is that you can use it with either of your proposed config options and probably others. For example if you're looking for something simple there's Pimple, a PHP Dependency Injection container written by the creator of the Symphoy PHP framework that in my opinion is great for smaller PHP projects http://pimple.sensiolabs.org/.
Upvotes: 0