From a flexibility point of View: This is totally correct.

But what from a RAM point of view.

Why have every .php script instanciate a new version of class config.php?

[cc lang=”php” escaped=”true” width=”600″]

I created an easy small class:

class Config {

private static $config = array();

public static function set( $key, $value ) {
self::$config[$key] = $value;
}

public static function get( $key ) {
return isset( self::$config[$key] ) ? self::$config[$key] : null;
}
}

[/cc]

Config::set( ‘my_config’, ‘the value’ );

echo ‘the config value is: ‘ . Config::get(‘my_config’);

this can easly be refactored to have a function isSet( $key ) or maybe a setAll( $array ).

EDIT: Now the syntax should be valid.

you can easily modify this class like follows:

[cc lang=”php” escaped=”true” width=”600″]
class Config {

private static $config = array();

public static function set( $key, $value ) {
self::$config[$key] = $value;
}

public static function get( $key ) {
return isset( self::$config[$key] ) ? self::$config[$key] : null;
}

public static function setAll( array $array ) {
self::$config = $array;
}

public static function isKeySet( $key ) {
return isset( self::$config[ $key ] );
}
}

Config::setAll( array(
‘key’ => ‘value’,
‘key2’ => array( ‘value’,
‘can be an’,
‘array’ ) ) );
Config::set( ‘my_config’, ‘the value’ );

if( Config::isKeySet( ‘my_config’ ) ) {
echo ‘the config value is: ‘ . Config::get(‘my_config’);
}
[/cc]

You still need to include the file in any another file that uses configs, or use an autoloader.

EDIT 2:

It’s pretty much the same as using a global, with the difference you don’t need to state that you want to use it in the beginning of every function. If you want to use Configs globally, then the Configs have to be, in some way global. When putting something in the global scope, you need to argue if this can be dangerous information to an other class not meant to see this information… default configurations? I think it’s safe to have in the global scope, and then you just need something that is easy to modify and customize.

If you decide that it’s dangerous information, that should not be reachable for a class other then the class it’s meant for, then you might want to check in to Dependency injection. With dependency injections a class will take an object in it’s constructor, placing it privately in a variable to use. This object can be an object from a configuration class, and then you need a wrapper class creating first the configuration object, and then the Template object injecting the configurations. This is a design often seen in more complex design patterns, like for instance Domain Driven Design.

“You have two ways:

a) either design your application in a way you got used to and you are familiar with (that will be better because you already have experience in it and you can predict how long the development will take and what problems may or may not arise); and after you will stuck into limitations of your current approach, refactor to avoid the globals;

b) look how its done in OOP frameworks (see at least three or four, i.e. Cake, CodeIgniter, Zend, Symfony, Flow3) and either borrow something, or switch to using a framework (or maybe you will be more sure that you do everything right).”

“The bigger your codebase gets, the more you have to decouple the individual parts from each other. If every part is dependent on every other part in your codebase, you simply cannot test, use or reuse any part of it individually. That simply devolves into chaos. To separate parts from each other, code them as classes or functions which take all their required data as parameters. That creates clean seams (interfaces) between different parts of your code.”

Trying to tie your question together into one example:

[cc lang=”php” escaped=”true” width=”600″]

require_once ‘Database.php’;
require_once ‘ConfigManager.php’;
require_once ‘Log.php’;
require_once ‘Foo.php’;

// establishes a database connection
$db = new Database(‘localhost’, ‘user’, ‘pass’);

// loads the configuration from the database,
// the dependency on the database is explicit without `global`
$configManager = new ConfigManager;
$config = $configManager->loadConfigurationFromDatabase($db);

// creates a new logger which logs to the database,
// note that it reuses the same $db as earlier
$log = new Log($db);

// creates a new Foo instance with explicit configuration passed,
// which was loaded from the database (or anywhere else) earlier
$foo = new Foo($config);

// executes the conversion function, which has access to the configuration
// passed at instantiation time, and also the logger which we created earlier
$foo->conversion(‘foo’, array(‘bar’, ‘baz’), $log);

[/cc]

 

I’ll leave to implementation of the individual classes up as an exercise for the reader. When you try to implement them, you’ll notice that they’re very easy and clear to implement and do not require a single global.

Every function and class gets all its necessary data passed in the form of function arguments. It should also be obvious that the above components can be plugged together in any other combination or that dependencies can easily be substituted for others. For example, the configuration does not need to come from the database at all, or the logger can log to a file instead of the database without Foo::conversion having to know about any of this.

Example implementation for ConfigManager:

[cc lang=”php” escaped=”true” width=”600″]

query(‘SELECT …’);

$config = array();
while ($row = $result->fetchRow()) {
$config[$row[‘name’]] = $row[‘value’];
}

return $config;
}

}[/cc]

Links:

http://stackoverflow.com/questions/12445972/stop-using-global-in-php

http://tomnomnom.com/posts/why-global-state-is-the-devil-and-how-to-avoid-using-it

liked this article?

  • only together we can create a truly free world
  • plz support dwaves to keep it up & running!
  • (yes the info on the internet is (mostly) free but beer is still not free (still have to work on that))
  • really really hate advertisement
  • contribute: whenever a solution was found, blog about it for others to find!
  • talk about, recommend & link to this blog and articles
  • thanks to all who contribute!
admin