Avatar of tonelm54
tonelm54
 asked on

GLOBALS

Ive often wondered this, and thought it would be a good time to ask
Why shouldnt you use GLOBALS?
Loads of forums say dont use GLOBAL variables, however are we saying pass the variables into the functions?

For example if I have a $db object (which hold the connection credentials etc for a database) which I want to use in another function, for I need to pass the reference $db into the function,  or surly its better to define $db as a global variable and use it in my second function.

I've read articles which suggest NEVER NEVER NEVER use Globals, but surely passing the reference $db into a function isnt/shouldnt be good practice? Or am I thinking wrong here?
PHP

Avatar of undefined
Last Comment
Ray Paseur

8/22/2022 - Mon
Chris Harte

The general consensus is that the use of globals is bad practise partly because they are difficult to debug and have excessive overhead. Globals are easy to override, and once you have done that debugging becomes almost impossible.

What ever problem you think you are solving by using globals you will find an easier, more logical, solution that does not use them.
Julian Hansen

While not directly addressing the "evil" of globals - this article is good reading to understand the thinking around the patterns that have been developed that specifically avoid globals

http://tutorials.jenkov.com/dependency-injection/dependency-injection-replacing-factory-patterns.html
Francisco Igor

If you are interested in make some variables available in your system, try another mechanism.
You can use some Class to get and set specific globals for your application, but do not use GLOBAL as a data store (class attributes instead).
If you declare some global variable more than once, nothing can alert you that your declaration is overwriting some variable in another side of your code.
If you create a class (or even a global function) you are in best position to ensure your code is not interfering with another code. For classes and functions, you are in control over your global resources.


Here is a basic example:

class App {

     var $db;
     var $anotherVar;


    public function connect(){
      //your connection code
      $this->db=$connection:
   }

   public function getDb(){
      if ($this->db===null) {
          $this->connect();
      }
     return $this->db;
  }

}

Open in new window


And then you can access it in your code (after including the class file)


function getData($id){
    App::getDb()->query("...");
  ....
}

Open in new window

Your help has saved me hundreds of hours of internet surfing.
fblack61
ASKER CERTIFIED SOLUTION
Ray Paseur

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
tonelm54

ASKER
Ok, so if I understand right I need to pass the reference of a database object, for example this wont work:-
<?php
class db {
     public function getDb(){
  		return "true";
  }
}

$dbConn = new db;

echo $dbConn->getDb();


class db2 {
     public function test(){
  		$dbConn->getDb();
  }
}

$ttt = new db2();
echo $ttt->test();

?>

Open in new window


However if I passed the variable of the database object to a new object can I reference it that, something like:-
<?php
class db {
     public function getDb(){
  		return "true";
  }
}

class db2 {
	var $db2Conn;
	
     public function __construct($dbConnection) {
  		$db2Conn = $dbConnection;
  }
	public function test() {
		$this->db2Conn->getDb();
	}
}



$dbConn = new db;
echo $dbConn->getDb();

$ttt = new db2($dbConn);
echo $ttt->test();

?>

Open in new window

Julian Hansen

Mostly - you need to add $this as below to be able to set the internal class variable.

public function __construct($dbConnection) {
   $this->db2Conn = $dbConnection; // Missing $this reference
}

Open in new window

Ray Paseur

This is hyper-simplified, but maybe it will illustrate the essential moving parts of dependency injection, showing how the $mysqli object is not used as a global, but is injected into the function.  Injection into object methods is exactly the same as injection into inline functions.  You just name the thing you want to inject among the variables that are listed in the function definition, and use the thing inside the function or method.
http://iconoun.com/demo/mysqli_di_example.php

<?php // demo/mysqli_di_example.php

/**
 * Demonstrate Dependency Injection with a MySQLi Object
 *
 * Man Page References:
 * http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
 * http://php.net/manual/en/mysqli.overview.php
 * http://php.net/manual/en/class.mysqli.php
 * http://php.net/manual/en/class.mysqli-stmt.php
 * http://php.net/manual/en/class.mysqli-result.php
 * http://php.net/manual/en/class.mysqli-warning.php
 */

// RAISE THE ERROR REPORTING LEVEL TO THE HIGHEST POSSIBLE SETTING
ini_set('display_errors', TRUE);
error_reporting(E_ALL);
echo '<pre>';

// DATABASE CONNECTION AND SELECTION VARIABLES - GET THESE FROM YOUR HOSTING COMPANY
$db_host = "localhost"; // PROBABLY THIS IS OK
$db_name = "??";
$db_user = "??";
$db_word = "??";

// OPEN A CONNECTION TO THE DATA BASE SERVER AND SELECT THE DB
$mysqli = new mysqli($db_host, $db_user, $db_word, $db_name);

// DID THE CONNECT/SELECT WORK OR FAIL?
if ($mysqli->connect_errno)
{
    $err
    = "CONNECT FAIL: "
    . $mysqli->connect_errno
    . ' '
    . $mysqli->connect_error
    ;
    trigger_error($err, E_USER_ERROR);
}

// ACTIVATE THIS TO SHOW WHAT THE DB CONNECTION OBJECT LOOKS LIKE
// var_dump($mysqli);


// A FUNCTION THAT USES AN INJECTED DATABASE CONNECTION
function run_a_query($db, $query)
{
    if (!$res = $db->query($query))
	{
	    $err
	    = 'QUERY FAILURE:'
	    . ' ERRNO: '
	    . $mysqli->errno
	    . ' ERROR: '
	    . $mysqli->error
	    . ' QUERY: '
	    . $sql
	    ;
	    trigger_error($err, E_USER_ERROR);
	}
	$data = $res->fetch_object();
	return $data;
}


// USE THE FUNCTION BY INJECTING THE $mysqli OBJECT AND THE QUERY
$set = run_a_query($mysqli, 'SELECT 2+2 AS ANSWER');
var_dump($set);

Open in new window

⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Ray Paseur

I'm marking this as a "Good Question" since it inspired this article.  Thanks for asking a question that a lot of others can benefit from!