Amin Gholibeigian
Amin Gholibeigian

Reputation: 1366

Access a global variable in a PHP function

According to the most programming languages scope rules, I can access variables that are defined outside of functions inside them, but why doesn't this code work?

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $data . "]";
    }

    menugen();
?>

The output is [].

Upvotes: 107

Views: 167795

Answers (10)

mickmackusa
mickmackusa

Reputation: 47883

Ultimately, it only makes sense to pass the required data into the function's scope as a parameter. Demo

$data = 'My data';
function menugen($arg) {
    echo "[" . $arg . "]";
}
menugen($data);

However, if your actual situation is more nuanced and you do not wish to follow the above advice, you can enjoy PHP7.4's arrow function syntax which allows inward-only access to values declared outside of the callback scope. Demo

$data = 'My data';
$menugen = fn() => "[$data]";
echo $menugen();

Or anonymously, you can Immediately Invoke a Function Expression: Demo

$data = 'My data';
echo (fn() => "[$data]")();

Upvotes: 0

donvercety
donvercety

Reputation: 241

Another way to do it:

<?php

$data = 'My data';

$menugen = function() use ($data) {

    echo "[".$data."]";
};

$menugen();

As of PHP 5.3.0 we have anonymous functions support that can create closures. A closure can access the variable which is created outside of its scope.

In the example, the closure is able to access $data because it was declared in the use clause.

Upvotes: 20

hlorand
hlorand

Reputation: 1406

The proper way for accessing a global variable inside a function is answered above!

BUT if you do not want to use the global keyword, nor the $GLOBALS variable for some reason (for example you have multiple functions and you are "tired" of writing global $variable; every time), here is a workaround:

$variable = 42;  // the global variable you want to access

// write a function which returns it
function getvar(){ 
    global $variable; 
    return $variable; 
}

//--------------

function func1()
{
    // use that getter function to get the global variable
    echo getvar();  // 42
}

function func2()
{
    echo getvar();  // 42
}
...

Upvotes: -1

Matteo Tassinari
Matteo Tassinari

Reputation: 18584

To address the question as asked, it is not working because you need to declare which global variables you'll be accessing in the function itself:

$data = 'My data';

function menugen() {
    global $data; // <-- Add this line

    echo "[" . $data . "]";
}

menugen();

Otherwise you can access it as $GLOBALS['data'], see Variable scope.

Even if a little off-topic, I would suggest you avoid using globals at all and prefer passing data as parameters.

In this case, the above code look like this:

$data = 'My data';

function menugen($data) { // <-- Declare the parameter
    echo "[" . $data . "]";
}

menugen($data); // <-- And pass it at call time

Upvotes: 207

Bob Smith
Bob Smith

Reputation: 151

I was looking for this answer, sort of, I wanted to see if anyone else had something similar with respect to how $prefix would be passed to an anonymous function. Seems the global scope is the the way? This is my solution for prefixing an array in a non-destructive manner.

private function array_prefix($prefix, $arr) {
  $GLOBALS['prefix'] = $prefix;
  return array_map(
    function($ele) {
      return $GLOBALS['prefix'].$ele;
    },
    $arr
  );
}

Upvotes: -1

Michael Aaron Wilson
Michael Aaron Wilson

Reputation: 1030

PHP can be frustrating for this reason. The answers above using global did not work for me, and it took me awhile to figure out the proper use of use.

This is correct:

$functionName = function($stuff) use ($globalVar) {
 //do stuff
}
$output = $functionName($stuff);
$otherOutput = $functionName($otherStuff);

This is incorrect:

function functionName($stuff) use ($globalVar) {
 //do stuff
}
$output = functionName($stuff);
$otherOutput = functionName($otherStuff);

Using your specific example:

    $data = 'My data';

    $menugen = function() use ($data) {
        echo "[" . $data . "]";
    }

    $menugen();

Upvotes: 0

Psalms Kalu
Psalms Kalu

Reputation: 115

For many years I have always used this format:

<?php
    $data = "Hello";

    function sayHello(){
        echo $GLOBALS["data"];
    }

    sayHello();
?>

I find it straightforward and easy to follow. The $GLOBALS is how PHP lets you reference a global variable. If you have used things like $_SERVER, $_POST, etc. then you have reference a global variable without knowing it.

Upvotes: 6

Sanjeev Budha
Sanjeev Budha

Reputation: 45

<?php

    $data = 'My data';

    $menugen = function() use ($data) {

        echo "[ $data ]";
    };

    $menugen();
?>

You can also simplify

echo "[" . $data . "]"

to

echo "[$data]"

Upvotes: -2

jcbwlkr
jcbwlkr

Reputation: 7999

You can do one of the following:

<?php
    $data = 'My data';

    function menugen() {
        global $data;
        echo "[" . $data . "]";
    }

    menugen();

Or

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $GLOBALS['data'] . "]";
    }

    menugen();

That being said, overuse of globals can lead to some poor code. It is usually better to pass in what you need. For example, instead of referencing a global database object you should pass in a handle to the database and act upon that. This is called dependency injection. It makes your life a lot easier when you implement automated testing (which you should).

Upvotes: 23

webnoob
webnoob

Reputation: 15934

It's a matter of scope. In short, global variables should be avoided so:

You either need to pass it as a parameter:

$data = 'My data';

function menugen($data)
{
    echo $data;
}

Or have it in a class and access it

class MyClass
{
    private $data = "";

    function menugen()
    {
        echo this->data;
    }

}

See @MatteoTassinari answer as well, as you can mark it as global to access it, but global variables are generally not required, so it would be wise to re-think your coding.

Upvotes: 14

Related Questions