访问 PHP 函数中的全局变量

根据大多数编程语言的作用域规则,我可以访问在函数之外定义的变量,但是为什么这段代码不能工作呢?

<?php
$data = 'My data';


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


menugen();
?>

输出是 []

150060 次浏览

You need to pass the variable into the function:

$data = 'My data';


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

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

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.

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).

Another way to do it:

<?php


$data = 'My data';


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


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


$menugen();

UPDATE 2020-01-13: requested by Peter Mortensen

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.

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.

<?php


$data = 'My data';


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


echo "[ $data ]";
};


$menugen();
?>

You can also simplify

echo "[" . $data . "]"

to

echo "[$data]"

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();

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
);
}

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
}
...