What's the difference between function &foo() and function foo(&$var) in PHP?
Example in code:
<?php
function foo(&$var){
$var++;
}
function &bar(){
$a= 5;
return $a;
}
foo( bar() );
The main issue here is who wants to alter or read whose variable.
In the first example you want the outer variable to be changed by the function. In example two you want the outer world to change the inner variable. And you can get changed values from the different scope.
A better use case for the second version would be:
class example {
public $test = 23;
public function &exposeTest() {
return $this->test;
}
}
$example1 = new example;
$testref = &$example1->exposeTest();
$testref++;
echo($example1->test); // 24
$example1->test++;
echo($testref); // 25
So it is not really a difference besides design issues and without OOP may not matter any way.
Related
This question may be silly. But an anonymous function does not really seem that anonymous to me. Maybe I am understanding it wrong, but an anonymous function must be stored in some variable, so it can later be referenced by this variable. If this is the case, what makes the below function so anonymous or so different than a regular function (other than the ability to store the function itself in a variable)? Or to word it differently, how is an anonymous function MORE useful than a regular function?
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
function greet($name)
{
printf("Hello %s\r\n", $name);
}
$greet('World');
$greet('PHP');
greet('World');
greet('PHP');
?>
Imagine you want to sort a list of users by username. Instead of defining a named comparison function that you're only going to use once, you can use an anonymous function:
usort($users, function($a, $b) {
return strcmp($a['username'], $b['username']);
});
The function itself has no name, as you show in your example you can still create a "real" function with the "same name". They're usually used like this as callbacks, which may seem more "anonymous":
foo(function ($bar) { ... });
One useful thing about anonymous (or lambda, if you prefer) functions is that they allow for creating your callback function inline with the code that needs it, rather than setting up a global function that will only be used in that one context. For instance:
$foo = native_function($bar, callback_function);
can be instead :
$foo = native_function($bar, function() { return $bar + 1; } );
Another handy thing about anonymous functions is that the variable you set it to calls that function every time, so it's not storing a value, but deriving it instead. This is great if a variable represents some derived value. Example:
$tax = .1;
$total = function() use (&$price, &$tax) { return $price * (1 + $tax); };
$price = 5.00;
echo $total(); // prints 5.50
$price = $price + 1;
echo $total(); // prints 6.60
$discount = $total() - 2;
echo $discount; // prints 4.60;
Instead of having to call a function like get_total and passing it $price every time, you interact with a variable that is always set to the newest value because it derives that value every time with the lambda function.
Lets say we have function:
function foo() {
return "bar";
}
Is it possible to add some filter to foo() function, for example to make it returning double value like "barbar" without changing the function itself.
So we would have:
foo(); //returns "bar"
function filter($&val) {
$val = $val . $val;
}
add_filter_to_function('foo','filter');
foo(); //returns "barbar"
And then anywhere foo() is used, it would return filtered value without changing code that calls foo() to something like foo() . foo() and without changing the function itself
In PHP, there is a RunKit extension (runkit_function_redefine() in particular for your question) which allow you to manipulate with code's objects (such as function or classes) on the fly.
But I think you're doing something wrong if you need to change your function's code on that way - so may be you should reconsider your goal and resolve your original problem with another tools.
If you need to call your function with some parameters in some special cases, you can use something like:
function foo($x, $y)
{
//do stuff
}
function bar($x, $y, $z)
{
//do stuff with $z?
foo($x, $y);
}
and use bar() instead of foo() then - in certain places (which you need to adjust)
You cannot internally change the return value of a function, if it's static.
If you had foo($var), you could change the state of $var, and everytime you call foo($var) lately, you would recieve the new value, but in your case it's almost not possible.
You have to call the other function everytime you need double value:
function foo() {
return 'bar';
}
function filter($func) {
return $func.$func;
}
echo filter(foo());
Turn your function into an object method and then the add_filter_to_function would add the filter to the object.
Then when you called the function it would be able to use the filters that have been assigned to the object the function belongs to.
You could simply concatenate the value on itself:
$val = foo();
$val .= $val;
or if your function really needs to have a double value returned, then you should probably look at refactoring your foo() function, because it doesn't seem to do what you want.
Either that, or accept one of the other answers that tells you to wrap foo() around another function.
If I try this code :
<?php
class ref
{
public $reff = "original ";
public function &get_reff()
{
return $this->reff;
}
public function get_reff2()
{
return $this->reff;
}
}
$thereffc = new ref;
$aa =& $thereffc->get_reff();
echo $aa;
$aa = " the changed value ";
echo $thereffc->get_reff(); // says "the changed value "
echo $thereffc->reff; // same thing
?>
Then returning by reference works and the value of the object property $reff gets changed as the variable $aa that references it changes too.
However, when I try this on a normal function that is not inside a class, it won't work !!
I tried this code :
<?php
function &foo()
{
$param = " the first <br>";
return $param;
}
$a = & foo();
$a = " the second <br>";
echo foo(); // just says "the first" !!!
it looks like the function foo() wont recognize it returns by reference and stubbornly returns what it wants !!!
Does returning by reference work only in OOP context ??
That is because a function's scope collapses when the function call completes and the function local reference to the variable is unset. Any subsequent calls to the function create a new $param variable.
Even if that where not the case in the function you are reassigning the variable to the first <br> with each invocation of the function.
If you want proof that the return by reference works use the static keyword to give the function variable a persistent state.
See this example
function &test(){
static $param = "Hello\n";
return $param;
}
$a = &test();
echo $a;
$a = "Goodbye\n";
echo test();
Echo's
Hello
Goodbye
Does returning by reference work only in OOP context ??
No. PHP makes no difference if that is a function or a class method, returning by reference always works.
That you ask indicates you might have not have understood fully what references in PHP are, which - as we all know - can happen. I suggest you read the whole topic in the PHP manual and at least two more sources by different authors. It's a complicated topic.
In your example, take care which reference you return here btw. You set $param to that value - always - when you call the function, so the function returns a reference to that newly set variable.
So this is more a question of variable scope you ask here:
Variable scope
I have seen in my journey to creaitng and building some of my php applications, the & symbol within front of vars, = and class names.
I understand that these are PHP References, but the docs i have seen and looked at seem to just not explain it in a way that i understand or confusing. How can you explain the following examples that i have seen to make them more understandable.
public static function &function_name(){...}
$varname =& functioncall();
function ($var, &$var2, $var3){...}
Much appreciated
Let's say you have two functions
$a = 5;
function withReference(&$a) {
$a++;
}
function withoutReference($a) {
$a++;
}
withoutReference($a);
// $a is still 5, since your function had a local copy of $a
var_dump($a);
withReference($a);
// $a is now 6, you changed $a outside of function scope
var_dump($a);
So, passing argument by reference allows function to modify it outside of the function scope.
Now second example.
You have a function which returns a reference
class References {
public $a = 5;
public function &getA() {
return $this->a;
}
}
$references = new References;
// let's do regular assignment
$a = $references->getA();
$a++;
// you get 5, $a++ had no effect on $a from the class
var_dump($references->getA());
// now let's do reference assignment
$a = &$references->getA();
$a++;
// $a is the same as $reference->a, so now you will get 6
var_dump($references->getA());
// a little bit different
$references->a++;
// since $a is the same as $reference->a, you will get 7
var_dump($a);
Reference functions
$name = 'alfa';
$address = 'street';
//declaring the function with the $ tells PHP that the function will
//return the reference to the value, and not the value itself
function &function_name($what){
//we need to access some previous declared variables
GLOBAL $name,$address;//or at function declaration (use) keyword
if ($what == 'name')
return $name;
else
return $address;
}
//now we "link" the $search variable and the $name one with the same value
$search =& function_name('name');
//we can use the result as value, not as reference too
$other_search = function_name('name');
//any change on this reference will affect the "$name" too
$search = 'new_name';
var_dump($search,$name,$other_search);
//will output string 'new_name' (length=8)string 'new_name' (length=8)string 'alfa' (length=4)
Usually you use the method with Objects that implemented the same interface, and you want to choose the object you want to work with next.
Passing by reference:
function ($var, &$var2, $var3){...}
I'm sure you saw the examples, so I'll just explain how and when to use it.
The basic scenario is when do you have a big logic that you want to apply to a current object/data, and you do not wish to make more copies of it (in memory).
Hope this helps.
I'm trying to return a value from a method as a reference in PHP5.3. I may be going at this the completely wrong way, but I am bringing an older project up to speed with some of the newer 5.3+ features.
Below is an example I whipped up to explain what is happening:
class Foo
{
static $foobar = 5;
function &bar()
{
return self::$foobar;
}
}
// Doesn't work
//$test1 = &call_user_func_array(array("Foo","bar"),array());
// Doesn't work
//$test1 = &call_user_func_array("Foo::bar",array());
// Doesn't work
//$f = new Foo; $test1 = &call_user_func_array(array($f,"bar"),array());
// WORKS
//$test1 = &Foo::bar();
//Doesn't work
//$function = "Foo::bar";
//$test1 = &$function();
// WORKS
$f = new Foo; $test1 = &$f->bar();
$test2 = Foo::bar();
var_dump($test1);
var_dump($test2);
$test1 = 10;
echo "----------<br />";
var_dump($test1);
var_dump($test2);
var_dump(Foo::bar()); //returns 10 when working, 5 when not working
The very last Foo::bar() should return a 10, since $test1 should be a reference to Foo::$foobar when everything works.
I realize that this example also uses some funky legacy PHP calling Foo::bar and the method bar() not being specified as static, but still being able to be invoked via ::
Any help would be greatly appreciated as the only fix I have so far is to just setup a switch on the argument list, and call the method directly based upon how many arguments exist.
This is just assigning $test1 to the value of $foobar (which is 5)
$test1 = &$f->bar();
This is just overwriting the value contained in $test1 with 10
$test1 = 10;
If you want to update the value within Foo, use
$f->foobar = 10;
Doesn't it already work in PHP 5.2.5: http://codepad.org/uMEIK210 (note the 10 as final result)?
I suppose, you would like to see the 10 three times.
For that (that $test2 is also a reference to the class field) you need to specify the & on both sides:
function &bar() and $test2 =& Foo::bar();
See the docs:
Note: Unlike parameter passing, here you have to use & in both places - to indicate that you want to return by reference, not a copy, and to indicate that reference binding, rather than usual assignment, should be done for $myValue.
So you just need to edit one line to get the (probably) desired 3 x 10:
$test2 =& Foo::bar();
Final hint
Do not use PHP references
First of all, try declaring the function static. Also the call should be a normal call. prefixed by ampersand as already answered.
class Foo
{
static $foobar = 5;
public static function &bar()
{
return self::$foobar;
}
}
The call:
$test1 =& Foo::bar();
Also, I can't see a valid reason for referencing a static variable. A static variable is a variable that doesn't change value between calls. It basically is a "global" var enclosed in a namespace. You only need read access from outside the class, the write should be done internally, as per the encapsulation principle. No need for the reference, really..