Reputation: 1366
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
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
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
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
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
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
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
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
Reputation: 45
<?php
$data = 'My data';
$menugen = function() use ($data) {
echo "[ $data ]";
};
$menugen();
?>
You can also simplify
echo "[" . $data . "]"
to
echo "[$data]"
Upvotes: -2
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
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