global vs $GLOBALS in php - php

I know it's better to use passing by reference instead of doing this, but i'm wondering why would this code (Code 1) work fine but the other (Code 2) wouldn't ?
Code 1:
<?php
$var = 5;
function unset_var() {
unset($GLOBALS['var']);
}
unset_var();
echo $var; //Notice: Undefined variable: var
?>
Code 2:
<?php
$var = 5;
function unset_var() {
global $var;
unset($var); // trying to unset $var
}
unset_var();
echo $var; // 5
?>

Your second code has a function that creates a new variable and you're unsetting that one, not the one outside the function. Your first code manipulates only the $GLOBALS array.
Also you should avoid even thinking about global variables in the first place....

Related

Why does the behavior like unset() in case of global variables is not the same for other operations too?

As per the PHP documentation on unset() function :
The behavior of unset() inside of a function can vary depending on what type of variable you are attempting to destroy.
If a globalized variable is unset() inside of a function, only the local variable is destroyed. The variable in the calling environment will retain the same value as before unset() was called.
The code example demonstrating above saying is as below :
<?php
function destroy_foo()
{
global $foo;
unset($foo);
}
$foo = 'bar';
destroy_foo();
echo $foo; // o/p is bar
?>
Now my question is why the above behavior is not applicable in following program that I have written?
<?php
function increment_foo()
{
global $foo;
$foo++;
}
$foo = 36;
increment_foo();
echo $foo; // o/p is 37
?>
My doubt is why the behavior is different in above code than the behavior in the code written for unset() function?
In other words, I want to know in first code the unset() functionality remains limited to the local variable inside the function, it doesn't change the value in global scope outside the function but in the code that I have been written the increment functionality changes the value in global variable scope as well. In my code why it's not remaining limited to the local variable inside a function and changing value/affecting the variable outside the function as well?
Thank You.
The reason for this is that using the global keyword will create a local variable referencing the variable in the global scope. Unsetting simply destroys this reference. It's similar to this piece of code:
$foo = 42; // create variable with value
$bar = &$foo; // create reference to $foo
$bar++; // increment $foo via reference
unset($bar); // destroy reference
var_dump($bar); // NULL
var_dump($foo); // 43
Another way to put it is that doing global $foo is just a shorthand for doing $foo = &$GLOBALS['foo'], e.g. the first example can be rewritten to
function increment_foo()
{
$foo = &$GLOBALS['foo'];
$foo++;
unset($foo);
var_dump($foo); // NULL
}
$foo = 42;
increment_foo();
var_dump($foo); // 43
Maybe that makes it more obvious that you are only destroying the reference, e.g. you are destroying what points to $foo, but not $foo itself.

Use variable variables with superglobal arrays

I wonder if is possible to read dynamically superglobal variables, I would like to do something like that:
<?php
$n = 'GET';
$var = '$_'.$n.'[\'something\']'; // pour lire $_GET['something']
echo $var;
//Or
$n = 'POST';
$var = '$_'.$n.'[\'something\']'; // pour lire $_POST['something']
echo $var;
?>
This code don't work as I want, but I would like to know if is workable in PHP?
You can't use variable variables with superglobals, functions or class methods and not with $this.
And a quote from the manual (It's right before the user comments if you search it):
Warning:
Please note that variable variables cannot be used with PHP's Superglobal arrays within functions or class methods. The variable $this is also a special variable that cannot be referenced dynamically.
Thank you is exactelly what I search
But we can't use that into function please?
$n = '_GET';
// don't work => Undefined variable: _GET
function f($n) {
echo ${$n}['a'];
}
f($n);
//work fine
echo ${$n}['a'];

PHP 5.4 Anonymous Function in Array undefine

This is PHP 5.4 code...
<?php
function abc($YesNo){return $YesNo["value"];}
$YesNo = array("value"=>"No","text"=>"No");
$x = array("active"=>function(){return abc($YesNo);});
echo $x['active']();
?>
Notice: Undefined variable: YesNo on line 7
Output Should be : Yes
if i directly put array in code by replace $YesNo like
<?php
function abc($YesNo){return $YesNo["value"];}
$x = array("active"=>function(){return abc(array("value"=>"Yes","text"=>"Yes"));});
echo $x['active']();
?>
output : Yes
which is correct output. Now what's the problem in first code. I need that for re-usability
Try this,
You can use use for passing data to a closure.
<?php
function abc($YesNo){return $YesNo["value"];}
$YesNo = array("value"=>"No","text"=>"No");
$x = array("active"=>function() use ($YesNo) {return abc($YesNo);});
echo $x['active']();
?>
You provide your anonymous function with a parameter:
$x = array("active"=>function($param){return abc($param);});
then you call it:
echo $x['active']($YesNo);
You may use the use keyword to make your function aware of an external variable:
$x = array("active"=>function() use ($YesNo) {return abc($YesNo);});
but it would be quite against the idea of reusability, in this case.
The problem is that your variable is not accessible within the function due to Variable Scope.
Because the array is defined outside of the function, it is not by default available inside the function.
There's a couple of solutions
Disclaimer: These are intended to fit within the scope of the question. I understand that they are not necessarily best practice, which would require a larger discussion
First Option:
You can declare the array within the function, like below. This is useful if you don't need access to it outside of the function.
function abc($YesNo){
$YesNo = array("value"=>"No","text"=>"No");
return $YesNo["value"];
}
Second Option:
Within your abc function, you can add the line global $YesNo. This is useful if you do need access to the array outside of the function:
function abc($YesNo){
global $YesNo;
return $YesNo["value"];
}
Other options exist (such as moonwave99's answer).
Finally:
Why are you putting an anonymous function within the array of $x? Seems like a path that will lead to problems down the road....
Your variable $YesNo needs to be visible in the scope of your anonymous function. You need to add global $YesNo as the first statement in that function:
So
$x = array("active"=>function(){return abc($YesNo);});
becomes
$x = array("active"=>function(){global $YesNo; return abc($YesNo);});
... also "value"=>"No" should be "value"=>"Yes" if you want it to return "Yes"

PHP. by using "global $var" to get a global variable, do we get a copy of the global var or get a reference to that global variable?

global $user vs $user = $GLOBALS['user']
by using "global $var" to get a global variable, do we get a copy of the global var or get a reference to that global variable?
global $user;
Is $user a copy of global object or is a reference to actual global variable?
Thanks.
by using it with global $var; you always have a local variable that references the global variable.
Following code:
$var = 1;
function test() {
global $var;
$var++;
}
test();
echo $var;
is equivalent to:
$var = 1;
function test() {
$GLOBALS['var']++;
}
test();
echo $var;
By using global $var the global variable named "var" will be imported into the local scope of the function (that is done by creating a reference).
That is different to $GLOBALS which is a superglobal variable. That is always everywhere regardless of the scope.
However that's different to references. If you really want to understand about the variables and how this is with references to variables, I suggest the PDF by Derick Rethans: References in PHP: An In-Depth Look (PDF).
Quoting $GLOBALS' documentation:
An associative array containing references to all variables which are currently defined in the global scope of the script. The variable names are the keys of the array.
A simple test case:
$foo = "foo";
echo $GLOBALS["foo"]; // foo
echo $GLOBALS["foo"] = "bar"; // bar
echo $foo; // bar
Neither. The compiler resolves usage of that variable name to the corresponding variable in global scope.

php passing by reference difference

I have a simple question here. Is there a difference between passing a variable by reference in a function parameter like:
function do_stuff(&$a)
{
// do stuff here...
}
and do it inside the function like:
function do_stuff($a)
{
$var = &$a;
// do stuff here...
}
What are the differences (if any) between using these two?. Also, can anybody give me a good tutorial that explains passing by reference? I can't seem to grasp this concept 100%.
Thank you
Here's a set of examples so you can see what happens with each of your questions.
I also added a third function which combines both of your questions because it will also produce a different result.
function do_stuff(&$a)
{
$a = 5;
}
function do_stuff2($a)
{
$var = &$a;
$var = 3;
}
function do_stuff3(&$a)
{
$var = &$a;
$var = 3;
}
$a = 2;
do_stuff($a);
echo $a;
echo '<br />';
$a = 2;
do_stuff2($a);
echo $a;
echo '<br />';
$a = 2;
do_stuff3($a);
echo $a;
echo '<br />';
They're not at all equivalent. In the second version, you're creating a reference to an undefined variable $a, causing $var to point to that same null value. Anything you do to $var and $a inside the second version will not affect anything outside of the function.
In the first version, if you change $a inside the function, the new value will be present outside after the function returns.
In your first example, if you modify $a inside the function in any way, the original value outside the function will be modified as well.
In your second example, whatever you do to $a or its reference $var will not modify the original value outside the function.
In the second function, the $a passed into the function is a copy of the argument passed in, (unless $a is an object), so you are making a $var a reference to the $a inside the function but it will still be separate from the variable passed to the function.
Assuming you are using a recent version of PHP, objects are automatically passed by reference too, so that could make a difference.

Categories