The value of global variables inside a function is NULL

In my code, I have a file that initializes the MySQLi class.

File a

:

$db = new Database(); //MySQLi class

      

Anyway, there is a file that includes this database class. This file also includes other files that have a function declared in it. I use global

for contact$db

File b

:

function xy(){
   global $db;
   $sql = "..."
   return $db->getArray($sql);
}

      

Testfile

:

require "file_a.php";
require "file_b.php";
require_once "PHPUnit/Framework/TestCase.php";

class testProblemStatistics extends PHPUnit_Framework_TestCase {

  testArray(){
      $this->assertTrue(array_key_exists('xy', $this->xy())
  }
}

      

I am getting:
Fatal error: Calling member function getArray () on non-object

I researched:

var_dump($db);
function xy(){
  global $db;
  var_dump($db);
  ...
}

      

The first dump gave me a MySQLi object , the
second dump gave me NULL

There is something wrong with the global variable in file_b.

Additional info: I am using PHPUnit and I am running it on the command line. Everything works fine in a normal browser.

+3


source to share


4 answers


The solution is to hardcode the database class into an array $GLOBALS

.

$GLOBALS['db'] = $db;

      



Adding this as a PHPUnit boot buffer works fine for me. This is kind of hacking and should be used in test cases.

+9


source


You should fully understand PHPUnit 's global state manual :

By default PHPUnit runs your tests so that changes to global and super-global variables ($ GLOBALS, $ _ENV, $ _POST, $ _GET, $ _COOKIE, $ _SERVER, $ _FILES, $ _REQUEST) do not affect other tests. Optionally, this isolation can be extended to static class attributes.

Most likely, a global variable $ db is created during the test. So after the test, it is removed to zero. You can either set a global variable in setUp (), or you can control how you want PHPUnit to behave with this global one yourself. There are several ways to do this.

Toggle @backupGlobals and it will not perform backup / restore operation between tests:

<?php

function xy(  ) {
    global $foo;
    var_dump( $foo ); 
    return $foo;
}

/**
 * @backupGlobals disabled
 */
class someTestCase extends PHPUnit_Framework_TestCase {

    public function testA(  ) {
        global $foo;
        $foo = 'bar';
    }  

    public function testB(  ) {
        global $foo;
        $this->assertEquals( $foo, 'bar' ); 
    }  
}

      



Do you understand why it @backupGlobals enabled

makes the test fail if you @backupGlobals disabled

do this?

If you want to back up / restore global variables except for $ db, define a class attribute like this:

protected $backupGlobalsBlacklist = array( 'db' );

      

This works too. In fact, it would be even better, as it would be nice to do some test isolation.

+4


source


It seems that when run in PHPUnit, the top-level code in file a is executed inside some method, and the assignment to $ db refers to a local variable. Make it explicitly global so it stays that way in your test run:

global $db;
$db = new Database(); //MySQLi class

      

+3


source


This answer by zerkms helps me: fooobar.com/questions/648789 / ... :

I bet you are executing this code by including this file in another function.

So, you need to mark the global primary variable as well .

Btw, globals are weird, an easier and more correct way to pass data to a function is to use function parameters.

0


source







All Articles