Recently i was studying the "Passing by Reference", I come to know following ways
What is the main difference between the following methods.
1.
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
2.
function foo($var)
{
$var++;
}
$a=5;
foo(&$a);
3.
function foo(&$var)
{
$var++;
}
function &bar()
{
$a = 5;
return $a;
}
foo(bar());
even though all of them produce same results, and which is the best way to work with.
Thanks.
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
This accepts a parameter that is always passed by reference (the & is in foo(&$var)). When $a is passed, it's always as a reference, so incrementing the variable inside the function will cause the parameter to be modified.
function foo($var)
{
$var++;
}
$a=5;
foo(&$a);
Do not use this. This is call-time pass-by-reference (you're passing &$a, a reference to $a, into the function), and is deprecated as of PHP 5.3.0. It's bad practice because the function doesn't expect a reference.
function foo(&$var)
{
$var++;
}
function &bar()
{
$a = 5;
return $a;
}
foo(bar());
This returns a reference (the & is in &bar()) to a variable $a declared in the function bar(). It then takes a reference to the return value of bar() and increments it. I'm not sure at a glance why this would be useful, though, especially for primitive/scalar types.
The second method is deprecated and should never be used.
Typically the function should just return the value.
function foo($a)
{
$a = 5;
}
$a = foo($a);
That's basically what the third method is doing. Not sure why you included an embedded pass by reference.
Pass by reference (for scalars and arrays) should generally be avoided because it's less clear than returning the value. However, it can be useful in cases where you need to modify multiple values within one function call.
Note that in PHP5, there's not even a need to explicitly pass an object by reference if you simply want to modify the original object, as the handle to the object will point to the same object as was passed to the function.
The last example is not equivalent to the first two. If you print the value of $a after calling foo, you will see that it is not defined. The third is basically an obfuscated no-op.
Related
I have this function that doesn't work.
$b is an outside string that should bond with $a array that should return a group of strings.
$a=array('this','is');
function chkEdt($a,$b) {
$a[]=$b;
};
print_r($a);
Result -> array();
Why?
You need to make it a reference parameter.
function chkEdt(&$a,$b) {
$a[]=$b;
};
Then any changes to $a in the function will affect the array variable that's used as the argument.
Your example never actually calls the chkEdt function, and that function never returns anything.
Aside from that, variables have different scope inside and outside functions - even though they share a name, they are considered to be different variables because one of them is inside a function. Read https://php.net/manual/en/language.variables.scope.php for more detail.
You can either pass the variable by reference as in Barmar's answer, or you can make the function return a value and then re-assign the $a outside the function to the value returned by the function - like this:
$a = array('this','is');
function chkEdt($a,$b) {
$a[] = $b;
return $a;
};
$a = chkEdt($a, "a");
print_r($a);
Live demo: http://sandbox.onlinephpfunctions.com/code/00d19028b3909ca415b81e93c26a6ede9188c743
To clarify the difference, you could re-write the function with a different variable name within the function, and get the same result:
$a = array('this','is');
function chkEdt($z,$b) {
$z[] = $b;
return $z;
};
$a = chkEdt($a, "a");
print_r($a);
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 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.
Is it possible to pass functions by reference?
Something like this:
function call($func){
$func();
}
function test(){
echo "hello world!";
}
call(test);
I know that you could do 'test', but I don't really want that, as I need to pass the function by reference.
Is the only way to do so via anonymous functions?
Clarification: If you recall from C++, you could pass a function via pointers:
void call(void (*func)(void)){
func();
}
Or in Python:
def call(func):
func()
That's what i'm trying to accomplish.
For what it's worth, how about giving something like this a shot? (Yes, I know it's an anonymous function which was mentioned in the post, but I was disgruntled at the abundance of replies that did not mention closures/function-objects at all so this is mostly a note for people running across this post.)
I don't use PHP, but using a closure appears to work in PHP 5.3 (but not PHP 5.2) as demonstrated here. I am not sure what the limitations, if any, there are. (For all I know the closure will eat your children. You have been warned.)
function doIt ($fn) {
echo "doIt\n";
return $fn();
}
function doMe () {
echo "doMe\n";
}
// I am using a closure here.
// There may be a more clever way to "get the function-object" representing a given
// named function, but I do not know what it is. Again, I *don't use PHP* :-)
echo doIt(function () { doMe(); });
Happy coding.
The problem with call_user_func() is that you're passing the return value of the function called, not the function itself.
I've run into this problem before too and here's the solution I came up with.
function funcRef($func){
return create_function('', "return call_user_func_array('{$func}', func_get_args());");
}
function foo($a, $b, $c){
return sprintf("A:%s B:%s C:%s", $a, $b, $c);
}
$b = funcRef("foo");
echo $b("hello", "world", 123);
//=> A:hello B:world C:123
ideone.com demo
No, functions are not first class values in PHP, they cannot be passed by their name literal (which is what you're asking for). Even anonymous functions or functions created via create_function are passed by an object or string reference.
You can pass a name of a function as string, the name of an object method as (object, string) array or an anonymous function as object. None of these pass pointers or references, they just pass on the name of the function. All of these methods are known as the callback pseudo-type: http://php.net/callback
function func1(){
echo 'echo1 ';
return 'return1';
}
function func2($func){
echo 'echo2 ' . $func();
}
func2('func1');
Result:
echo1 echo2 return1
In PHP 5.4.4 (haven't tested lower or other versions), you can do exactly as you suggested.
Take this as an example:
function test ($func) {
$func('moo');
}
function aFunctionToPass ($str) {
echo $str;
}
test('aFunctionToPass');
The script will echo "moo" as if you called "aFunctionToPass" directly.
A similar pattern of this Javascript first class function:
function add(first, second, callback){
console.log(first+second);
if (callback) callback();
}
function logDone(){
console.log('done');
}
function logDoneAgain(){
console.log('done Again');
}
add(2,3, logDone);
add(3,5, logDoneAgain);
Can be done in PHP (Tested with 5.5.9-1ubuntu on C9 IDE) in the following way:
// first class function
$add = function($first, $second, $callback) {
echo "\n\n". $first+$second . "\n\n";
if ($callback) $callback();
};
function logDone(){
echo "\n\n done \n\n";
}
call_user_func_array($add, array(2, 3, logDone));
call_user_func_array($add, array(3, 6, function(){
echo "\n\n done executing an anonymous function!";
}));
Result: 5 done 9 done executing an anonymous function!
Reference: https://github.com/zenithtekla/unitycloud/commit/873659c46c10c1fe5312f5cde55490490191e168
You can create a reference by assigning the function to a local variable when you declare it:
$test = function() {
echo "hello world!";
};
function call($func){
$func();
}
call($test);
You can say
$fun = 'test';
call($fun);
Instead of call(test);, use call_user_func('test');.
As of PHP 8.1, you can use First-class callables:
call(test(...));
You can even use methods:
call($obj->test(...));
As simple as it is.
It appears a bit unclear why do you want to pass functions by reference? Usually things are passed by reference only when the referenced data needs to be (potentially) modified by the function.
As PHP uses arrays or strings to refer functions, you could just pass an array or a string by reference and that would allow the function reference to be modified.
For example, you could do something like
<?php
$mysort = function($a, b) { return ($a < $b) ? 1 : -1; };
adjust_sort_from_config($mysort); // modifies $mysort
do_something_with_data($mysort);
where
<?php
function load_my_configuration(&$fun)
{
$sort_memory = new ...;
...
$fun = [$sort_memory, "customSort"];
// or simply
$fun = function($a, b) { return (rand(1,10) < 4 ? 1 : -1; };
}
This works because there are three ways to refer to function in PHP via a variable:
$name – the string $name contains the name of the function in global namespace that should be called
array($object, $name) – refers to method called string $name of object $object.
array($class, $name) – refers to static function string $name of class $class.
If I remember correctly, the methods and static functions pointed by these constructs must be public. The "First-class callable syntax" should improve this restriction given recent enough PHP version but it seems to be just some syntactic sugar around Closure::fromCallable().
Anonymous functions work the same behind the scenes. You just don't see the literal random names of those functions anywhere but the reference to an anonymous function is just a value of a variable, too.