Ivan Seidel
Ivan Seidel

Reputation: 2362

Global variable in PHP is not working

I need to access $layers from inside the function isOk($layer), but everything i tried the outside function variable $layers is ok, but inside the function, even with global is return null.

Here is the code:

$layers = array();
foreach($pcb['PcbFile'] as $file){
    if(!empty($file['layer'])){
        $layers[$file['layer']] = 'ok';
    }
}
// Prints OK!
var_dump($layers);

function isOk($layer){
    global $layers;
// Not OK! prints NULL
    var_dump($layers);
    if(array_key_exists($layer, $layers))
        return ' ok';
    return '';
}
// NOT OK
echo isOk('MD');

I always use Object orientation, but this was something so simple that i made with a simple function... Why $layers is not being 'received' correcly inside the function?

Upvotes: 1

Views: 3476

Answers (2)

cHao
cHao

Reputation: 86505

Watch this...

HalfAssedFramework.php

<?php
class HalfAssedFramework {
    public static function run($path) {
        include $path;
    }
}

HalfAssedFramework::run('example.php');

example.php

<?php

$layers = array();
foreach($pcb['PcbFile'] as $file){
    if(!empty($file['layer'])){
        $layers[$file['layer']] = 'ok';
    }
}
// Prints OK!
var_dump($layers);

function isOk($layer){
    global $layers;
// Not OK! prints NULL
    var_dump($layers);
    if(array_key_exists($layer, $layers))
        return ' ok';
    return '';
}
// NOT OK
echo isOk('MD');

Run example.php directly, and it should work. Run HalfAssedFramework.php, and it won't.

The problem is scope. When example.php is included inside the run function, all the code inside it inherits the function's scope. In that scope, $layers isn't global by default.

To fix this, you have a couple of options:

  • If you know example.php will never run directly, you can say global $layers; at the beginning of the file. I'm not sure whether this will work if the script is run directly, though.
  • Replace $layers with $GLOBALS['layers'] everywhere.
  • Add $layers as an argument to isOk.
  • Put this code within a class, as suggested by Geoffrey.

Upvotes: 6

Geoffrey Bachelet
Geoffrey Bachelet

Reputation: 4317

Not exactly answering the question, but have you considered not using globals? Globals really aren't that cool: they make your code harder to read, harder to understand and as a consequence, harder to maintain.

Consider something like that:

<?php

class LayerCollection
{
    private $layers;

    public function __construct($layers)
    {
        $this->layers = $layers;
    }

    public static function fromPcbFile($data)
    {
        $layers = array();

        foreach ($data['PcbFile'] as $layer) {
            if (!empty($layer)) {
                $layers[$layer] = true;
            }
        }

        return new self($layers);
    }

    public function hasLayer($layer)
    {
        return array_key_exists($layer, $this->layers);
    }
}

$layers = LayerCollection::fromPcbFile($pcb);
var_dump($layers->hasLayer('MD'));

Doesn't it look better? You can then proceed to enrich LayerCollection as you need more ways of interacting with your layers. This is not perfect, since there's still a static method lying around (makes testing harder, a factory would be better suited for that job), but that's a good start for a refactoring.

More about why globals are evil: https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil

Upvotes: 2

Related Questions