Stop using `global` in PHP - php

I have a config.php that is included to each page. In config I create an array that looks something like:
$config = array();
$config['site_name'] = 'Site Name';
$config['base_path'] = '/home/docs/public_html/';
$config['libraries_path'] = $config['base_path'] . '/libraries';
//etc...
Then I have function.php, that is also included to almost each page, where I have to use global $config to get access to it - and this is what I would like to get rid of!
How do I access $config in the other parts of my code without using global?
Could anyone explain, WHY I shouldn't use global in my example? Some say it's a bad tone, others say it's not secure?
EDIT 1:
Example of where and how I use it:
function conversion($Exec, $Param = array(), $Log = '') {
global $config;
$cmd = $config['phppath'] . ' ' . $config['base_path'] . '/' . $Exec;
foreach ($Param as $s)
{
$cmd .= ' ' . $s;
}
}
EDIT 2:
Putting all of this in the class, as suggested by Vilx, would be cool but in this case, how would I tie it with the following loop that is extracting config key and value from database. I oversimplified the idea of assigning $config array, here is an example:
$sql = "SELECT * from settings";
$rsc = $db->Execute($sql);
if ( $rsc ) {
while(!$rsc->EOF) {
$field = $rsc->fields['setting_options'];
$config[$field] = $rsc->fields['setting_values'];
#$rsc->MoveNext();
}
}
EDIT 3:
Besides, I have to access other vars from functions that are set in config and it's few of them, e.g.:$db, $language and etc.
If I put them in the class will it really solve anything? If I use global what does it really change?
EDIT 4:
I read PHP global in functions where Gordon explains in the very nice way why you shouldn't use global. I agree on everything but I don't use global in my case to reassign the variables, which will result in, like he said, <-- WTF!!, ;)) yeah agree, it's crazy. But if I just need to access database from a function just by using global $db where is the problem in this case? How do you do this otherwise, without using global?
EDIT 5:
In the same PHP global in functions deceze says: "The one big reason against global is that it means the function is dependent on another scope. This will get messy very quickly."
But I'm talking here about basic 'INIT'. I basically set define but use vars - well that is wrong in technical way. But your function is not depended on anything - but the name of one var $db that you could keep in mind? It's really global need to use $db, where is the DEPENDENCY here and how to use it otherwise?
P.S. I just had a thought, that we're facing the conflict here of two different minds, e.g.: mine (yet NOT well understanding object-oriented programming) and those who could be called gurus (from my current point of view) in OOP - what looks obvious for them for me arises new questions. I think that's why this question is being asked over and over again. Personally for me it's gotten more clear after all but still there are things to clarify.

The point against global variables is that they couple code very tightly. Your entire codebase is dependent on a) the variable name $config and b) the existence of that variable. If you want to rename the variable (for whatever reason), you have to do so everywhere throughout your codebase. You can also not use any piece of code that depends on the variable independently of it anymore.
Example with global variable:
require 'SomeClass.php';
$class = new SomeClass;
$class->doSomething();
Anywhere in the above lines you may get an error because the class or some code in SomeClass.php implicitly depends on a global variable $config. There's no indication of this whatsoever though just looking at the class. To solve this, you have to do this:
$config = array(...);
require 'SomeClass.php';
$class = new SomeClass;
$class->doSomething();
This code may still fail somewhere if you do not set the correct keys inside $config. Since it's not obvious what parts of the config array SomeClass needs or doesn't need and when it needs them, it's hard to recreate the correct environment for it to run correctly. It also creates conflicts if you happened to already have a variable $config used for something else wherever you want to use SomeClass.
So instead of creating implicit, invisible dependencies, inject all dependencies:
require 'SomeClass.php';
$arbitraryConfigVariableName = array(...);
$class = new SomeClass($arbitraryConfigVariableName);
$class->doSomething();
By passing the config array explicitly as a parameter, all the above problems are solved. It's as simple as handing the required information around inside your app. It also makes the structure and flow of the application and what talks to what much clearer. To get to this state if your application is currently a big ball of mud may take some restructuring.
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:
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);
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:
class ConfigManager {
public function loadConfigurationFromDatabase(Database $db) {
$result = $db->query('SELECT ...');
$config = array();
while ($row = $result->fetchRow()) {
$config[$row['name']] = $row['value'];
}
return $config;
}
}
It's a very simple piece of code that doesn't even do much. You may ask why you'd want this as object oriented code. The point is that this makes using this code extremely flexible, since it isolates it perfectly from everything else. You give one database connection in, you get one array with a certain syntax back. Input → Output. Clear seams, clear interfaces, minimal, well defined responsibilities. You can do the same with a simple function.
The extra advantage an object has is that it even further decouples the code that calls loadConfigurationFromDatabase from any particular implementation of that function. If you'd just use a global function loadConfigurationFromDatabase(), you basically have the same problem again: that function needs to be defined when you try to call it and there are naming conflicts if you want to replace it with something else. By using an object, the critical part of the code moves here:
$config = $configManager->loadConfigurationFromDatabase($db);
You can substitute $configManager here for any other object that also has a method loadConfigurationFromDatabase. That's "duck typing". You don't care what exactly $configManager is, as long as it has a method loadConfigurationFromDatabase. If it walks like a duck and quacks like a duck, it is a duck. Or rather, if it has a loadConfigurationFromDatabase method and gives back a valid config array, it's some sort of ConfigManager. You have decoupled your code from one particular variable $config, from one particular loadConfigurationFromDatabase function and even from one particular ConfigManager. All parts can be changed and swapped out and replaced and loaded dynamically from anywhere, because the code does not depend on any one particular other piece.
The loadConfigurationFromDatabase method itself also does not depend on any one particular database connection, as long as it can call query on it and fetch results. The $db object being passed into it could be entirely fake and read its data from an XML file or anywhere else instead, as long as its interface still behaves the same.

I've solved this with a class:
class Config
{
public static $SiteName = 'My Cool Site';
}
function SomeFunction
{
echo 'Welcome to ' , Config::$SiteName;
}
fcortes' suggestion to use constants is also a good one. I'd only like to suggest to give all constants a prefix, like CFG_SITE_NAME, so to avoid accidental name clashes with other constants.

For your case I would create an only file constants.php with definitions (if your purpose is these "variables" never be changed in execution time):
define('SITE_NAME','site name');
define('BASE_PATH','/home/docs/public_html/');
...
Include this constants.php in all files where you will need it:
include_once('constants.php');

There is a big discussing between object-oriented and procedural approaches (and more generally, between declarative and imperative ones) and each approach has its upsides and downsides.
I used 'Config' class that was a Singleton (an OOP version of global). It worked good for me until I had discovered a need to use several of previously-developed solutions together in one application - since all configs were global and referred by the same class (the same variable name, in your case) they conflicted and I had to switch to proper config every time I called code from other sub-application.
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).

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;
}
}
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:
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');
}
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.

config.php
<?php
class config {
private static $config = array();
public static function set( $key, $value ) {
self::$config[$key] = $value;
}
public static function get( $key ) {
if( config::isKeySet( $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 ] );
}
}
// set valuable values
config::setAll( array(
'key' => 'value',
'key2' => array( 'value', 'can be an', 'array' ),
'database' => array( "username" => "root", "password" => "root")
)
);
config::set( 'my_config', 'the value' );
?>
config.usage.php
<?php
require_once 'config.php';
$database_credentials = config::get('database');
echo 'the config value for username is ' . $database_credentials['username'];
echo '<br> the config value for password is ' . $database_credentials['password'];
function additionalFunctionality($database_credentials)
{
echo '<br> the config value for password is ' . $database_credentials['password'];
}
?>
config.usage.too.php
<?php
require_once 'config.php'; // put this first
require_once 'config.usage.php'; // include some functionality from another file
$database_credentials = Config::get('database');
echo 'the config value for username is ' . $database_credentials['username'];
additionalFunctionality($database_credentials); // great
?>

Related

Php Mysqli Global DB define for Classes ? [duplicate]

I have a config.php that is included to each page. In config I create an array that looks something like:
$config = array();
$config['site_name'] = 'Site Name';
$config['base_path'] = '/home/docs/public_html/';
$config['libraries_path'] = $config['base_path'] . '/libraries';
//etc...
Then I have function.php, that is also included to almost each page, where I have to use global $config to get access to it - and this is what I would like to get rid of!
How do I access $config in the other parts of my code without using global?
Could anyone explain, WHY I shouldn't use global in my example? Some say it's a bad tone, others say it's not secure?
EDIT 1:
Example of where and how I use it:
function conversion($Exec, $Param = array(), $Log = '') {
global $config;
$cmd = $config['phppath'] . ' ' . $config['base_path'] . '/' . $Exec;
foreach ($Param as $s)
{
$cmd .= ' ' . $s;
}
}
EDIT 2:
Putting all of this in the class, as suggested by Vilx, would be cool but in this case, how would I tie it with the following loop that is extracting config key and value from database. I oversimplified the idea of assigning $config array, here is an example:
$sql = "SELECT * from settings";
$rsc = $db->Execute($sql);
if ( $rsc ) {
while(!$rsc->EOF) {
$field = $rsc->fields['setting_options'];
$config[$field] = $rsc->fields['setting_values'];
#$rsc->MoveNext();
}
}
EDIT 3:
Besides, I have to access other vars from functions that are set in config and it's few of them, e.g.:$db, $language and etc.
If I put them in the class will it really solve anything? If I use global what does it really change?
EDIT 4:
I read PHP global in functions where Gordon explains in the very nice way why you shouldn't use global. I agree on everything but I don't use global in my case to reassign the variables, which will result in, like he said, <-- WTF!!, ;)) yeah agree, it's crazy. But if I just need to access database from a function just by using global $db where is the problem in this case? How do you do this otherwise, without using global?
EDIT 5:
In the same PHP global in functions deceze says: "The one big reason against global is that it means the function is dependent on another scope. This will get messy very quickly."
But I'm talking here about basic 'INIT'. I basically set define but use vars - well that is wrong in technical way. But your function is not depended on anything - but the name of one var $db that you could keep in mind? It's really global need to use $db, where is the DEPENDENCY here and how to use it otherwise?
P.S. I just had a thought, that we're facing the conflict here of two different minds, e.g.: mine (yet NOT well understanding object-oriented programming) and those who could be called gurus (from my current point of view) in OOP - what looks obvious for them for me arises new questions. I think that's why this question is being asked over and over again. Personally for me it's gotten more clear after all but still there are things to clarify.
The point against global variables is that they couple code very tightly. Your entire codebase is dependent on a) the variable name $config and b) the existence of that variable. If you want to rename the variable (for whatever reason), you have to do so everywhere throughout your codebase. You can also not use any piece of code that depends on the variable independently of it anymore.
Example with global variable:
require 'SomeClass.php';
$class = new SomeClass;
$class->doSomething();
Anywhere in the above lines you may get an error because the class or some code in SomeClass.php implicitly depends on a global variable $config. There's no indication of this whatsoever though just looking at the class. To solve this, you have to do this:
$config = array(...);
require 'SomeClass.php';
$class = new SomeClass;
$class->doSomething();
This code may still fail somewhere if you do not set the correct keys inside $config. Since it's not obvious what parts of the config array SomeClass needs or doesn't need and when it needs them, it's hard to recreate the correct environment for it to run correctly. It also creates conflicts if you happened to already have a variable $config used for something else wherever you want to use SomeClass.
So instead of creating implicit, invisible dependencies, inject all dependencies:
require 'SomeClass.php';
$arbitraryConfigVariableName = array(...);
$class = new SomeClass($arbitraryConfigVariableName);
$class->doSomething();
By passing the config array explicitly as a parameter, all the above problems are solved. It's as simple as handing the required information around inside your app. It also makes the structure and flow of the application and what talks to what much clearer. To get to this state if your application is currently a big ball of mud may take some restructuring.
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:
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);
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:
class ConfigManager {
public function loadConfigurationFromDatabase(Database $db) {
$result = $db->query('SELECT ...');
$config = array();
while ($row = $result->fetchRow()) {
$config[$row['name']] = $row['value'];
}
return $config;
}
}
It's a very simple piece of code that doesn't even do much. You may ask why you'd want this as object oriented code. The point is that this makes using this code extremely flexible, since it isolates it perfectly from everything else. You give one database connection in, you get one array with a certain syntax back. Input → Output. Clear seams, clear interfaces, minimal, well defined responsibilities. You can do the same with a simple function.
The extra advantage an object has is that it even further decouples the code that calls loadConfigurationFromDatabase from any particular implementation of that function. If you'd just use a global function loadConfigurationFromDatabase(), you basically have the same problem again: that function needs to be defined when you try to call it and there are naming conflicts if you want to replace it with something else. By using an object, the critical part of the code moves here:
$config = $configManager->loadConfigurationFromDatabase($db);
You can substitute $configManager here for any other object that also has a method loadConfigurationFromDatabase. That's "duck typing". You don't care what exactly $configManager is, as long as it has a method loadConfigurationFromDatabase. If it walks like a duck and quacks like a duck, it is a duck. Or rather, if it has a loadConfigurationFromDatabase method and gives back a valid config array, it's some sort of ConfigManager. You have decoupled your code from one particular variable $config, from one particular loadConfigurationFromDatabase function and even from one particular ConfigManager. All parts can be changed and swapped out and replaced and loaded dynamically from anywhere, because the code does not depend on any one particular other piece.
The loadConfigurationFromDatabase method itself also does not depend on any one particular database connection, as long as it can call query on it and fetch results. The $db object being passed into it could be entirely fake and read its data from an XML file or anywhere else instead, as long as its interface still behaves the same.
I've solved this with a class:
class Config
{
public static $SiteName = 'My Cool Site';
}
function SomeFunction
{
echo 'Welcome to ' , Config::$SiteName;
}
fcortes' suggestion to use constants is also a good one. I'd only like to suggest to give all constants a prefix, like CFG_SITE_NAME, so to avoid accidental name clashes with other constants.
For your case I would create an only file constants.php with definitions (if your purpose is these "variables" never be changed in execution time):
define('SITE_NAME','site name');
define('BASE_PATH','/home/docs/public_html/');
...
Include this constants.php in all files where you will need it:
include_once('constants.php');
There is a big discussing between object-oriented and procedural approaches (and more generally, between declarative and imperative ones) and each approach has its upsides and downsides.
I used 'Config' class that was a Singleton (an OOP version of global). It worked good for me until I had discovered a need to use several of previously-developed solutions together in one application - since all configs were global and referred by the same class (the same variable name, in your case) they conflicted and I had to switch to proper config every time I called code from other sub-application.
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).
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;
}
}
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:
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');
}
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.
config.php
<?php
class config {
private static $config = array();
public static function set( $key, $value ) {
self::$config[$key] = $value;
}
public static function get( $key ) {
if( config::isKeySet( $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 ] );
}
}
// set valuable values
config::setAll( array(
'key' => 'value',
'key2' => array( 'value', 'can be an', 'array' ),
'database' => array( "username" => "root", "password" => "root")
)
);
config::set( 'my_config', 'the value' );
?>
config.usage.php
<?php
require_once 'config.php';
$database_credentials = config::get('database');
echo 'the config value for username is ' . $database_credentials['username'];
echo '<br> the config value for password is ' . $database_credentials['password'];
function additionalFunctionality($database_credentials)
{
echo '<br> the config value for password is ' . $database_credentials['password'];
}
?>
config.usage.too.php
<?php
require_once 'config.php'; // put this first
require_once 'config.usage.php'; // include some functionality from another file
$database_credentials = Config::get('database');
echo 'the config value for username is ' . $database_credentials['username'];
additionalFunctionality($database_credentials); // great
?>

What's the best way (coding-wise) to get config variables in PHP application

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.
Method 1: Using static class
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');
}
Method 2: Using instable object
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.
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.
Update:
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.
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/.

Global vs static variables in PHP

I'm creating a basic framework in PHP. I need to pass data for the current page into different functions, allow them to modify and save it, and then pass it back to the page to be displayed. I was originally planning on storing the data in a global variable like $GLOBALS['data'], but I'm starting to think that using a global is a bad idea. So I'm thinking that instead I will put a static variable in the system class, and access it using system::$data. So, my question is, which would be better and why?
This:
$GLOBALS['data'] = array();
$GLOBALS['data']['page_title'] = 'Home';
echo $GLOBALS['data']['page_title'];
Or this:
class system
{
public static $data = array()
}
function data($new_var)
{
system::$data = array_merge(system::$data, $new_var);
}
data(array('page_title' => 'Home'));
echo system::$data['page_title'];
There really is no difference between a global variable and a public static variable. The class variable is namespaced a tiny bit better, but that hardly makes any difference. Both are accessible anywhere at any time and both are global state.
As it happens, I just wrote an exhaustive article on the subject:
How Not To Kill Your Testability Using Statics
So, my question is, which would be better and why?
You already sense that there is some problem putting this all into globals. Although you have developed some thoughts to encapsulate things into a class.
I think that is a good starting point. Let's add some more spice to the cooking to get this more fluent at the beginning:
$data = new ArrayObject(array());
$data['page_title'] = 'Home';
You have created an object now that you can pass along containing your data. Just pass $data to the area's where it's needed. No global or global static variable needed.
You can even make that type more concrete later on by extending from ArrayObject with your own type.
For the record.
Pro of static:
Clarity of the code. For example:
function fn() {
System::data()
}
versus
function fn() {
global $system;
$system->data()
}
Cons of static:
If you are using psr-4 then you must add (and include) a new class (and a new file). It impacts the performance even if you use opcache (opcache aleviates it but it's not magic).
You must define a block of code.

What to use instead of a global variable? [duplicate]

For years I have used global $var,$var2,...,$varn for methods in my application. I've used them for two main implementations:
Getting an already set class (such as DB connection), and passing info to functions that display to page.
Example:
$output['header']['log_out'] = "Log Out";
function showPage(){
global $db, $output;
$db = ( isset( $db ) ) ? $db : new Database();
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
There are, however, performance and security ramifications of doing it like this.
What alternative practice can I use that will maintain my functionality but improve design, performance, and/or security?
This is the first question I've ever asked on SO, so if you need clarifications please comment!
1. Globals. Works like a charm. Globals are hated thus my thoughts of not using it.
Well, globals are not just hated. They are hated for a reason. If you didn't run so far into the problems globals cause, fine. There is no need for you to refactor your code.
2. Define a constant in my config.php file.
This is actually just like a global, but with another name. You would spare the $ as well and to use the global at the beginning of functions. Wordpress did this for their configuration, I'd say this is more bad than using global variables. It makes it much more complicated to introduce seams. Also you can not assign an object to a constant.
3. Include the config file in the function.
I'd consider this as overhead. You segmentize the codebase for not much gain. The "global" here will become the name of the file you inlcude btw..
Taken these three thoughts of you and my comments to them into account I'd say: Unless you run into actual issues with some global variables, you can stick to them. Global then work as your service locator (configuration, database). Others do much more to create the same.
If you run into problems (e.g. you probably want to develop test-driven), I suggest you start with putting one part after the other under test and then you learn how to avoid the globals.
Dependency Injection
As inside comments it became clear you're looking for dependency injection, and if you can not edit the function parameter definition, you can - if you use objects - inject dependencies via the constructor or by using so called setter methods. In the following example code I'll do both which is for demonstration purposes only as you might have guessed, it's not useful to use both at once:
Let's say the configuration array is the dependency we would like to inject. Let's call it config and name the variable $config. As it is an array, we can type-hint it as array. first of all define the configuration in a include file maybe, you could also use parse_ini_file if you prefer the ini-file format. I think it's even faster.
config.php:
<?php
/**
* configuration file
*/
return array(
'db_user' => 'root',
'db_pass' => '',
);
That file then can just be required inside your application where-ever you want to:
$config = require('/path/to/config.php');
So it can be easily turned into an array variable somewhere in your code. Nothing spectacular so far and totally unrelated to dependency injection. Let's see an exemplary database class which needs to have the configuration here, it needs to have the username and the password otherwise it can't connect let's say:
class DBLayer
{
private $config;
public function __construct(array $config)
{
$this->setConfig($config);
}
public function setConfig(array $config)
{
$this->config = $config;
}
public function oneICanNotChange($paramFixed1, $paramFixed2)
{
$user = $this->config['db_user'];
$password = $this->config['db_pass'];
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
throw new DBLayerException('Connection failed: ' . $e->getMessage());
}
...
}
This example is a bit rough, but it has the two examples of dependency injection. First via the constructor:
public function __construct(array $config)
This one is very common, all dependencies the class needs to do it's work are injection at creation time. This also ensures that when any other method of that object is called, the object will be in a pre-determinable state - which is somewhat important for a system.
The second example is to have a public setter method:
public function setConfig(array $config)
This allows to add the dependency later, but some methods might need to check for things being available prior doing their job. E.g. if you could create the DBLayer object without providing configuration, the oneICanNotChange method could be called without that object having configuration and should had to deal with that (which is not shown in this example).
Service Locator
As you need to probably integrate code on the fly and you want your new code to be put under test with dependency injection and all that what's making our live easier, you might need to put this together with your ancient / legacy code. I think that part is tough. Dependency injection on it's own is pretty easy, but putting this together with old code is not that straight forward.
What I can suggest here is that you make one global variable that is the so called service locator. It contains a central point to fetch objects (or even arrays like your $config) from. It can be used then and the contract is that single variable name. So to remove globals we make use of a global variable. Sounds a bit counter-productive and it even is if your new code uses it too much as well. However, you need some tool to bring old and new together. So here is the most bare PHP service locator implementation I could imagine so far.
It consists of one Services object that offers all of your services, like the config from above. Because when a PHP script starts, we yet do not know if a service at all is needed (e.g. we might not run any database query, so we don't need to instantiate the database), it offers some lazy initialization feature as well. This is done by using factory-scripts that are just PHP files that setup the service and return it.
A first example: Let's say the function oneICanNotChange would not have been part of an object but just a simple function in the global namespace. We would not have been able to inject config dependency. This is where the Services Service Locator object comes in:
$services = new Services(array(
'config' => '/path/to/config.php',
));
...
function oneICanNotChange($paramFixed1, $paramFixed2)
{
global $services;
$user = $services['config']['db_user'];
$password = $services['config']['db_pass'];
...
As the example already shows, the Services object does map the string 'config' to the path of the PHP file that defines the $config array: /path/to/config.php. It uses the ArrayAccess interface than to expose that service inside the oneICanNotChange function.
I suggest the ArrayAccess interface here, because it's well defined and it shows that we have some dynamic character here. On the other hand it allows us the lazy initialization:
class Services implements ArrayAccess
{
private $config;
private $services;
public function __construct(array $config)
{
$this->config = $config;
}
...
public function offsetGet($name)
{
return #$this->services[$name] ?
: $this->services[$name] = require($this->config[$name]);
}
...
}
This exemplary stub just requires the factory scripts if it has not done so far, otherwise will return the scripts return value, like an array, an object or even a string (but not NULL which makes sense).
I hope these examples are helpful and show that not much code is needed to gain more flexibility here and punching globals out of your code. But you should be clear, that the service locator introduces global state to your code. The benefit is just, that it's easier to de-couple this from concrete variable names and to provide a bit more flexibility. Maybe you're able to divide the objects you use in your code into certain groups, of which only some need to become available via the service-locator and you can keep the code small that depends on the locator.
The alternative is called dependency injection. In a nutshell it means that you pass the data a function/class/object requires as parameters.
function showPage(Database $db, array &$output) {
...
}
$output['header']['log_out'] = "Log Out";
$db = new Database;
showPage($db, $output);
This is better for a number of reasons:
localizing/encapsulating/namespacing functionality (the function body has no implicit dependencies to the outside world anymore and vice versa, you can now rewrite either part without needing to rewrite the other as long as the function call doesn't change)
allows unit testing, since you can test functions in isolation without needing to setup a specific outside world
it's clear what a function is going to do to your code just by looking at the signature
There are, however, performance and security ramifications of doing it like this.
To tell you truth, there are no performance nor security ramifications. Using globals is a matter of cleaner code, and nothing more. (Well, okay, as long as you're not passing variables of tens of megabytes in size)
So, you have to think first, will alternatives make cleaner code for you, or not.
In matters of cleaner code, I'd be in fear if I see a db connection in the function called showPage.
One option that some people may frown upon is to create a singleton object responsible for holding the application state. When you want to access some shared "global" object you could make a call like: State::get()->db->query(); or $db = State::get()->db;.
I see this method as a reasonable approach as it saves having to pass around a bunch of objects all over the place.
EDIT:
Using this approach can help simplify the organization and readability of your application. For example, your state class could call the proper methods to initialize your database object and decouple its initialization from your showPage function.
class State {
private static $instance;
private $_db;
public function getDB() {
if(!isset($this->_db)){
// or call your database initialization code or set this in some sort of
// initialization method for your whole application
$this->_db = new Database();
}
return $this->_db;
}
public function getOutput() {
// do your output stuff here similar to the db
}
private function __construct() { }
public static function get() {
if (!isset(self::$instance)) {
$className = __CLASS__;
self::$instance = new State;
}
return self::$instance;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Unserializing is not allowed.', E_USER_ERROR);
}
}
and your show page function could be something like this:
function showPage(){
$output = State::get()->getOutput();
$output['header']['title'] = State::get()->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
An alternative to using a singleton object is to pass the state object to your various functions, this allows you to have alternative "states" if your application gets complicated and you will only need to pass around a single state object.
function showPage($state){
$output = $state->getOutput();
$output['header']['title'] = $state->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
$state = new State; // you'll have to remove all the singleton code in my example.
showPage($state);
function showPage(&$output, $db = null){
$db = is_null( $db ) ? new Database() : $db;
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
and
$output['header']['log_out'] = "Log Out";
showPage($output);
$db =new Database();
showPage($output,$db);
Start designing your code in OOP, then you can pass config to the constructor. You could also encapsulate all your functions into a class.
<?php
class functions{
function __construct($config){
$this->config = $config;
}
function a(){
//$this->config is available in all these functions/methods
}
function b(){
$doseSomething = $this->config['someKey'];
}
...
}
$config = array(
'someKey'=>'somevalue'
);
$functions = new functions($config);
$result = $functions->a();
?>
Or if you cant refactor the script, loop through the config array and define constants.
foreach($config as $key=>$value){
define($key,$value);
}

Safe alternatives to PHP Globals (Good Coding Practices)

For years I have used global $var,$var2,...,$varn for methods in my application. I've used them for two main implementations:
Getting an already set class (such as DB connection), and passing info to functions that display to page.
Example:
$output['header']['log_out'] = "Log Out";
function showPage(){
global $db, $output;
$db = ( isset( $db ) ) ? $db : new Database();
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
There are, however, performance and security ramifications of doing it like this.
What alternative practice can I use that will maintain my functionality but improve design, performance, and/or security?
This is the first question I've ever asked on SO, so if you need clarifications please comment!
1. Globals. Works like a charm. Globals are hated thus my thoughts of not using it.
Well, globals are not just hated. They are hated for a reason. If you didn't run so far into the problems globals cause, fine. There is no need for you to refactor your code.
2. Define a constant in my config.php file.
This is actually just like a global, but with another name. You would spare the $ as well and to use the global at the beginning of functions. Wordpress did this for their configuration, I'd say this is more bad than using global variables. It makes it much more complicated to introduce seams. Also you can not assign an object to a constant.
3. Include the config file in the function.
I'd consider this as overhead. You segmentize the codebase for not much gain. The "global" here will become the name of the file you inlcude btw..
Taken these three thoughts of you and my comments to them into account I'd say: Unless you run into actual issues with some global variables, you can stick to them. Global then work as your service locator (configuration, database). Others do much more to create the same.
If you run into problems (e.g. you probably want to develop test-driven), I suggest you start with putting one part after the other under test and then you learn how to avoid the globals.
Dependency Injection
As inside comments it became clear you're looking for dependency injection, and if you can not edit the function parameter definition, you can - if you use objects - inject dependencies via the constructor or by using so called setter methods. In the following example code I'll do both which is for demonstration purposes only as you might have guessed, it's not useful to use both at once:
Let's say the configuration array is the dependency we would like to inject. Let's call it config and name the variable $config. As it is an array, we can type-hint it as array. first of all define the configuration in a include file maybe, you could also use parse_ini_file if you prefer the ini-file format. I think it's even faster.
config.php:
<?php
/**
* configuration file
*/
return array(
'db_user' => 'root',
'db_pass' => '',
);
That file then can just be required inside your application where-ever you want to:
$config = require('/path/to/config.php');
So it can be easily turned into an array variable somewhere in your code. Nothing spectacular so far and totally unrelated to dependency injection. Let's see an exemplary database class which needs to have the configuration here, it needs to have the username and the password otherwise it can't connect let's say:
class DBLayer
{
private $config;
public function __construct(array $config)
{
$this->setConfig($config);
}
public function setConfig(array $config)
{
$this->config = $config;
}
public function oneICanNotChange($paramFixed1, $paramFixed2)
{
$user = $this->config['db_user'];
$password = $this->config['db_pass'];
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
throw new DBLayerException('Connection failed: ' . $e->getMessage());
}
...
}
This example is a bit rough, but it has the two examples of dependency injection. First via the constructor:
public function __construct(array $config)
This one is very common, all dependencies the class needs to do it's work are injection at creation time. This also ensures that when any other method of that object is called, the object will be in a pre-determinable state - which is somewhat important for a system.
The second example is to have a public setter method:
public function setConfig(array $config)
This allows to add the dependency later, but some methods might need to check for things being available prior doing their job. E.g. if you could create the DBLayer object without providing configuration, the oneICanNotChange method could be called without that object having configuration and should had to deal with that (which is not shown in this example).
Service Locator
As you need to probably integrate code on the fly and you want your new code to be put under test with dependency injection and all that what's making our live easier, you might need to put this together with your ancient / legacy code. I think that part is tough. Dependency injection on it's own is pretty easy, but putting this together with old code is not that straight forward.
What I can suggest here is that you make one global variable that is the so called service locator. It contains a central point to fetch objects (or even arrays like your $config) from. It can be used then and the contract is that single variable name. So to remove globals we make use of a global variable. Sounds a bit counter-productive and it even is if your new code uses it too much as well. However, you need some tool to bring old and new together. So here is the most bare PHP service locator implementation I could imagine so far.
It consists of one Services object that offers all of your services, like the config from above. Because when a PHP script starts, we yet do not know if a service at all is needed (e.g. we might not run any database query, so we don't need to instantiate the database), it offers some lazy initialization feature as well. This is done by using factory-scripts that are just PHP files that setup the service and return it.
A first example: Let's say the function oneICanNotChange would not have been part of an object but just a simple function in the global namespace. We would not have been able to inject config dependency. This is where the Services Service Locator object comes in:
$services = new Services(array(
'config' => '/path/to/config.php',
));
...
function oneICanNotChange($paramFixed1, $paramFixed2)
{
global $services;
$user = $services['config']['db_user'];
$password = $services['config']['db_pass'];
...
As the example already shows, the Services object does map the string 'config' to the path of the PHP file that defines the $config array: /path/to/config.php. It uses the ArrayAccess interface than to expose that service inside the oneICanNotChange function.
I suggest the ArrayAccess interface here, because it's well defined and it shows that we have some dynamic character here. On the other hand it allows us the lazy initialization:
class Services implements ArrayAccess
{
private $config;
private $services;
public function __construct(array $config)
{
$this->config = $config;
}
...
public function offsetGet($name)
{
return #$this->services[$name] ?
: $this->services[$name] = require($this->config[$name]);
}
...
}
This exemplary stub just requires the factory scripts if it has not done so far, otherwise will return the scripts return value, like an array, an object or even a string (but not NULL which makes sense).
I hope these examples are helpful and show that not much code is needed to gain more flexibility here and punching globals out of your code. But you should be clear, that the service locator introduces global state to your code. The benefit is just, that it's easier to de-couple this from concrete variable names and to provide a bit more flexibility. Maybe you're able to divide the objects you use in your code into certain groups, of which only some need to become available via the service-locator and you can keep the code small that depends on the locator.
The alternative is called dependency injection. In a nutshell it means that you pass the data a function/class/object requires as parameters.
function showPage(Database $db, array &$output) {
...
}
$output['header']['log_out'] = "Log Out";
$db = new Database;
showPage($db, $output);
This is better for a number of reasons:
localizing/encapsulating/namespacing functionality (the function body has no implicit dependencies to the outside world anymore and vice versa, you can now rewrite either part without needing to rewrite the other as long as the function call doesn't change)
allows unit testing, since you can test functions in isolation without needing to setup a specific outside world
it's clear what a function is going to do to your code just by looking at the signature
There are, however, performance and security ramifications of doing it like this.
To tell you truth, there are no performance nor security ramifications. Using globals is a matter of cleaner code, and nothing more. (Well, okay, as long as you're not passing variables of tens of megabytes in size)
So, you have to think first, will alternatives make cleaner code for you, or not.
In matters of cleaner code, I'd be in fear if I see a db connection in the function called showPage.
One option that some people may frown upon is to create a singleton object responsible for holding the application state. When you want to access some shared "global" object you could make a call like: State::get()->db->query(); or $db = State::get()->db;.
I see this method as a reasonable approach as it saves having to pass around a bunch of objects all over the place.
EDIT:
Using this approach can help simplify the organization and readability of your application. For example, your state class could call the proper methods to initialize your database object and decouple its initialization from your showPage function.
class State {
private static $instance;
private $_db;
public function getDB() {
if(!isset($this->_db)){
// or call your database initialization code or set this in some sort of
// initialization method for your whole application
$this->_db = new Database();
}
return $this->_db;
}
public function getOutput() {
// do your output stuff here similar to the db
}
private function __construct() { }
public static function get() {
if (!isset(self::$instance)) {
$className = __CLASS__;
self::$instance = new State;
}
return self::$instance;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Unserializing is not allowed.', E_USER_ERROR);
}
}
and your show page function could be something like this:
function showPage(){
$output = State::get()->getOutput();
$output['header']['title'] = State::get()->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
An alternative to using a singleton object is to pass the state object to your various functions, this allows you to have alternative "states" if your application gets complicated and you will only need to pass around a single state object.
function showPage($state){
$output = $state->getOutput();
$output['header']['title'] = $state->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
$state = new State; // you'll have to remove all the singleton code in my example.
showPage($state);
function showPage(&$output, $db = null){
$db = is_null( $db ) ? new Database() : $db;
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
and
$output['header']['log_out'] = "Log Out";
showPage($output);
$db =new Database();
showPage($output,$db);
Start designing your code in OOP, then you can pass config to the constructor. You could also encapsulate all your functions into a class.
<?php
class functions{
function __construct($config){
$this->config = $config;
}
function a(){
//$this->config is available in all these functions/methods
}
function b(){
$doseSomething = $this->config['someKey'];
}
...
}
$config = array(
'someKey'=>'somevalue'
);
$functions = new functions($config);
$result = $functions->a();
?>
Or if you cant refactor the script, loop through the config array and define constants.
foreach($config as $key=>$value){
define($key,$value);
}

Categories