Difference between "use" and passing a parameter to controller function - php

I don't have a specific problem, just looking to deepen my understanding of what's going on with Silex and with some new-ish PHP features in general. This is based off the code samples on the "usage" page of the Silex documentation:
$blogPosts = array(
1 => array(
'date' => '2011-03-29',
'author' => 'igorw',
'title' => 'Using Silex',
'body' => '...', );
$app->get('/blog/{id}', function (Silex\Application $app, $id) use ($blogPosts) {
//do stuff
}
Questions
What is the difference here between passing the $app and $id as parameters to the function, and use-ing the $blogPosts variable?
Could $blogPosts also have been passed as a parameter to the function?
Also, I more commonly see use ($app). What is the difference between use-ing the $app and passing it is a parameter?

This has nothing to do with silex and everything to do with "some new-ish PHP features".
You are creating an anonymous function (also called a closure), reusable several times with different $app and $id values, BUT with only the same $blogPosts value.
<?php
$a = "a";
$b = "b";
$c = function ($d) use ($b) {
echo $d . "." . $b . PHP_EOL;
};
$b = "c";
$e = function ($d) use ($b) {
echo $d . "." . $b . PHP_EOL;
};
$c($a); // prints a.b, and not a.c
$e($a); // prints a.c
Here, i'm building a function with $b, and once it is build, I use it with variables that do not have to be named the same way the function's argument is named.

Maybe this makes it more transparent
<?php
$a = "a1";
$b = "b1";
$f = function ($x) use ($b) {
echo $x . $b;
};
$f($a); // prints a1b1
// now let's change values of $a and $b
$a = "a2";
$b = "b2"; //--> won't be used as $b was 'b1' when declaring the function.
$f($a); // prints a2b1
?>

The use allows to import variables from the parent scope into the closure scope.
It will allow the function get() to call your closure with the appropriate param $blogPosts imported from the parent scope.

Related

Trying to understand how this / parameters works [duplicate]

Are PHP variables passed by value or by reference?
It's by value according to the PHP Documentation.
By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference.
To have an argument to a function always passed by reference, prepend an ampersand (&) to the argument name in the function definition.
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>
In PHP, by default, objects are passed as reference to a new object.
See this example:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj->abc = 30;
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30
Now see this:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.
Now see this:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue(&$obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.
I hope you can understand this.
It seems a lot of people get confused by the way objects are passed to functions and what passing by reference means. Object are still passed by value, it's just the value that is passed in PHP5 is a reference handle. As proof:
<?php
class Holder {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
function swap($x, $y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
a, b
To pass by reference means we can modify the variables that are seen by the caller, which clearly the code above does not do. We need to change the swap function to:
<?php
function swap(&$x, &$y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
b, a
in order to pass by reference.
http://www.php.net/manual/en/migration5.oop.php
In PHP 5 there is a new Object Model. PHP's handling of objects has been completely rewritten, allowing for better performance and more features. In previous versions of PHP, objects were handled like primitive types (for instance integers and strings). The drawback of this method was that semantically the whole object was copied when a variable was assigned, or passed as a parameter to a method. In the new approach, objects are referenced by handle, and not by value (one can think of a handle as an object's identifier).
PHP variables are assigned by value, passed to functions by value and when containing/representing objects are passed by reference. You can force variables to pass by reference using an '&'.
Assigned by value/reference example:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
output:
var1: test, var2: final test, var3: final test
Passed by value/reference example:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
output:
var1: foo, var2 BAR
Object variables passed by reference example:
class Foo{
public $var1;
function __construct(){
$this->var1 = "foo";
}
public function printFoo(){
print $this->var1;
}
}
$foo = new Foo();
changeFoo($foo);
$foo->printFoo();
function changeFoo($foo){
$foo->var1 = "FOO";
}
output:
FOO
(The last example could be better probably.)
You can pass a variable to a function by reference. This function will be able to modify the original variable.
You can define the passage by reference in the function definition:
<?php
function changeValue(&$var)
{
$var++;
}
$result=5;
changeValue($result);
echo $result; // $result is 6 here
?>
You can do it either way.
Put an '&' symbol in front and the variable you are passing becomes one and the same as its origin i.e. you can pass by reference, rather than make a copy of it.
so
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
TL;DR: PHP supports both pass by value and pass by reference. References are declared using an ampersand (&); this is very similar to how C++ does it. When the formal parameter of a function is not declared with an ampersand (i.e., it's not a reference), everything is passed by value, including objects. There is no distinction between how objects and primitives are passed around. The key is to understand what gets passed along when you pass in objects to a function. This is where understanding pointers is invaluable.
For anyone who comes across this in the future, I want to share this gem from the PHP docs, posted by an anonymous user:
There seems to be some confusion here. The distinction between pointers and references is not particularly helpful.
The behavior in some of the "comprehensive" examples already posted can be explained in simpler unifying terms. Hayley's code, for example, is doing EXACTLY what you should expect it should. (Using >= 5.3)
First principle:
A pointer stores a memory address to access an object. Any time an object is assigned, a pointer is generated. (I haven't delved TOO deeply into the Zend engine yet, but as far as I can see, this applies)
2nd principle, and source of the most confusion:
Passing a variable to a function is done by default as a value pass, ie, you are working with a copy. "But objects are passed by reference!" A common misconception both here and in the Java world. I never said a copy OF WHAT. The default passing is done by value. Always. WHAT is being copied and passed, however, is the pointer. When using the "->", you will of course be accessing the same internals as the original variable in the caller function. Just using "=" will only play with copies.
3rd principle:
"&" automatically and permanently sets another variable name/pointer to the same memory address as something else until you decouple them. It is correct to use the term "alias" here. Think of it as joining two pointers at the hip until forcibly separated with "unset()". This functionality exists both in the same scope and when an argument is passed to a function. Often the passed argument is called a "reference," due to certain distinctions between "passing by value" and "passing by reference" that were clearer in C and C++.
Just remember: pointers to objects, not objects themselves, are passed to functions. These pointers are COPIES of the original unless you use "&" in your parameter list to actually pass the originals. Only when you dig into the internals of an object will the originals change.
And here's the example they provide:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}
?>
I wrote an extensive, detailed blog post on this subject for JavaScript, but I believe it applies equally well to PHP, C++, and any other language where people seem to be confused about pass by value vs. pass by reference.
Clearly, PHP, like C++, is a language that does support pass by reference. By default, objects are passed by value. When working with variables that store objects, it helps to see those variables as pointers (because that is fundamentally what they are, at the assembly level). If you pass a pointer by value, you can still "trace" the pointer and modify the properties of the object being pointed to. What you cannot do is have it point to a different object. Only if you explicitly declare a parameter as being passed by reference will you be able to do that.
Variables containing primitive types are passed by value in PHP5. Variables containing objects are passed by reference. There's quite an interesting article from Linux Journal from 2006 which mentions this and other OO differences between 4 and 5.
http://www.linuxjournal.com/article/9170
Objects are passed by reference in PHP 5 and by value in PHP 4.
Variables are passed by value by default!
Read here: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
class Holder
{
private $value;
public function __construct( $value )
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function setValue( $value )
{
return $this->value = $value;
}
}
class Swap
{
public function SwapObjects( Holder $x, Holder $y )
{
$tmp = $x;
$x = $y;
$y = $tmp;
}
public function SwapValues( Holder $x, Holder $y )
{
$tmp = $x->getValue();
$x->setValue($y->getValue());
$y->setValue($tmp);
}
}
$a1 = new Holder('a');
$b1 = new Holder('b');
$a2 = new Holder('a');
$b2 = new Holder('b');
Swap::SwapValues($a1, $b1);
Swap::SwapObjects($a2, $b2);
echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";
echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";
Attributes are still modifiable when not passed by reference so beware.
Output:
SwapObjects: b, a
SwapValues: a, b
Regarding how objects are passed to functions you still need to understand that without "&", you pass to the function an object handle , object handle that is still passed by value , and it contains the value of a pointer. But you can not change this pointer until you pass it by reference using the "&"
<?php
class Example
{
public $value;
}
function test1($x)
{
//let's say $x is 0x34313131
$x->value = 1; //will reflect outsite of this function
//php use pointer 0x34313131 and search for the
//address of 'value' and change it to 1
}
function test2($x)
{
//$x is 0x34313131
$x = new Example;
//now $x is 0x88888888
//this will NOT reflect outside of this function
//you need to rewrite it as "test2(&$x)"
$x->value = 1000; //this is 1000 JUST inside this function
}
$example = new Example;
$example->value = 0;
test1($example); // $example->value changed to 1
test2($example); // $example did NOT changed to a new object
// $example->value is still 1
?>
Use this for functions when you wish to simply alter the original variable and return it again to the same variable name with its new value assigned.
function add(&$var){ // The & is before the argument $var
$var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
Actually both methods are valid but it depends upon your requirement. Passing values by reference often makes your script slow. So it's better to pass variables by value considering time of execution. Also the code flow is more consistent when you pass variables by value.
A PHP reference is an alias, allowing two different variables to write to the same value.
And in PHP, if you have a variable that contains an object, that variable does not contain the object itself. Instead, it contains an identifier for that object. The object accessor will use the identifier to find the actual object. So when we use the object as an argument in function or assign it to another variable, we will be copying the identifier that points to the object itself.
https://hsalem.com/posts/you-think-you-know-php.html
class Type {}
$x = new Type();
$y = $x;
$y = "New value";
var_dump($x); // Will print the object.
var_dump($y); // Will print the "New value"
$z = &$x; // $z is a reference of $x
$z = "New value";
var_dump($x); // Will print "New value"
var_dump($z); // Will print "New value"
Depends on the version, 4 is by value, 5 is by reference.

PHP "filled" function parameters [duplicate]

Are PHP variables passed by value or by reference?
It's by value according to the PHP Documentation.
By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference.
To have an argument to a function always passed by reference, prepend an ampersand (&) to the argument name in the function definition.
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>
In PHP, by default, objects are passed as reference to a new object.
See this example:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj->abc = 30;
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30
Now see this:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.
Now see this:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue(&$obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.
I hope you can understand this.
It seems a lot of people get confused by the way objects are passed to functions and what passing by reference means. Object are still passed by value, it's just the value that is passed in PHP5 is a reference handle. As proof:
<?php
class Holder {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
function swap($x, $y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
a, b
To pass by reference means we can modify the variables that are seen by the caller, which clearly the code above does not do. We need to change the swap function to:
<?php
function swap(&$x, &$y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
b, a
in order to pass by reference.
http://www.php.net/manual/en/migration5.oop.php
In PHP 5 there is a new Object Model. PHP's handling of objects has been completely rewritten, allowing for better performance and more features. In previous versions of PHP, objects were handled like primitive types (for instance integers and strings). The drawback of this method was that semantically the whole object was copied when a variable was assigned, or passed as a parameter to a method. In the new approach, objects are referenced by handle, and not by value (one can think of a handle as an object's identifier).
PHP variables are assigned by value, passed to functions by value and when containing/representing objects are passed by reference. You can force variables to pass by reference using an '&'.
Assigned by value/reference example:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
output:
var1: test, var2: final test, var3: final test
Passed by value/reference example:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
output:
var1: foo, var2 BAR
Object variables passed by reference example:
class Foo{
public $var1;
function __construct(){
$this->var1 = "foo";
}
public function printFoo(){
print $this->var1;
}
}
$foo = new Foo();
changeFoo($foo);
$foo->printFoo();
function changeFoo($foo){
$foo->var1 = "FOO";
}
output:
FOO
(The last example could be better probably.)
You can pass a variable to a function by reference. This function will be able to modify the original variable.
You can define the passage by reference in the function definition:
<?php
function changeValue(&$var)
{
$var++;
}
$result=5;
changeValue($result);
echo $result; // $result is 6 here
?>
You can do it either way.
Put an '&' symbol in front and the variable you are passing becomes one and the same as its origin i.e. you can pass by reference, rather than make a copy of it.
so
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
TL;DR: PHP supports both pass by value and pass by reference. References are declared using an ampersand (&); this is very similar to how C++ does it. When the formal parameter of a function is not declared with an ampersand (i.e., it's not a reference), everything is passed by value, including objects. There is no distinction between how objects and primitives are passed around. The key is to understand what gets passed along when you pass in objects to a function. This is where understanding pointers is invaluable.
For anyone who comes across this in the future, I want to share this gem from the PHP docs, posted by an anonymous user:
There seems to be some confusion here. The distinction between pointers and references is not particularly helpful.
The behavior in some of the "comprehensive" examples already posted can be explained in simpler unifying terms. Hayley's code, for example, is doing EXACTLY what you should expect it should. (Using >= 5.3)
First principle:
A pointer stores a memory address to access an object. Any time an object is assigned, a pointer is generated. (I haven't delved TOO deeply into the Zend engine yet, but as far as I can see, this applies)
2nd principle, and source of the most confusion:
Passing a variable to a function is done by default as a value pass, ie, you are working with a copy. "But objects are passed by reference!" A common misconception both here and in the Java world. I never said a copy OF WHAT. The default passing is done by value. Always. WHAT is being copied and passed, however, is the pointer. When using the "->", you will of course be accessing the same internals as the original variable in the caller function. Just using "=" will only play with copies.
3rd principle:
"&" automatically and permanently sets another variable name/pointer to the same memory address as something else until you decouple them. It is correct to use the term "alias" here. Think of it as joining two pointers at the hip until forcibly separated with "unset()". This functionality exists both in the same scope and when an argument is passed to a function. Often the passed argument is called a "reference," due to certain distinctions between "passing by value" and "passing by reference" that were clearer in C and C++.
Just remember: pointers to objects, not objects themselves, are passed to functions. These pointers are COPIES of the original unless you use "&" in your parameter list to actually pass the originals. Only when you dig into the internals of an object will the originals change.
And here's the example they provide:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}
?>
I wrote an extensive, detailed blog post on this subject for JavaScript, but I believe it applies equally well to PHP, C++, and any other language where people seem to be confused about pass by value vs. pass by reference.
Clearly, PHP, like C++, is a language that does support pass by reference. By default, objects are passed by value. When working with variables that store objects, it helps to see those variables as pointers (because that is fundamentally what they are, at the assembly level). If you pass a pointer by value, you can still "trace" the pointer and modify the properties of the object being pointed to. What you cannot do is have it point to a different object. Only if you explicitly declare a parameter as being passed by reference will you be able to do that.
Variables containing primitive types are passed by value in PHP5. Variables containing objects are passed by reference. There's quite an interesting article from Linux Journal from 2006 which mentions this and other OO differences between 4 and 5.
http://www.linuxjournal.com/article/9170
Objects are passed by reference in PHP 5 and by value in PHP 4.
Variables are passed by value by default!
Read here: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
class Holder
{
private $value;
public function __construct( $value )
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function setValue( $value )
{
return $this->value = $value;
}
}
class Swap
{
public function SwapObjects( Holder $x, Holder $y )
{
$tmp = $x;
$x = $y;
$y = $tmp;
}
public function SwapValues( Holder $x, Holder $y )
{
$tmp = $x->getValue();
$x->setValue($y->getValue());
$y->setValue($tmp);
}
}
$a1 = new Holder('a');
$b1 = new Holder('b');
$a2 = new Holder('a');
$b2 = new Holder('b');
Swap::SwapValues($a1, $b1);
Swap::SwapObjects($a2, $b2);
echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";
echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";
Attributes are still modifiable when not passed by reference so beware.
Output:
SwapObjects: b, a
SwapValues: a, b
Regarding how objects are passed to functions you still need to understand that without "&", you pass to the function an object handle , object handle that is still passed by value , and it contains the value of a pointer. But you can not change this pointer until you pass it by reference using the "&"
<?php
class Example
{
public $value;
}
function test1($x)
{
//let's say $x is 0x34313131
$x->value = 1; //will reflect outsite of this function
//php use pointer 0x34313131 and search for the
//address of 'value' and change it to 1
}
function test2($x)
{
//$x is 0x34313131
$x = new Example;
//now $x is 0x88888888
//this will NOT reflect outside of this function
//you need to rewrite it as "test2(&$x)"
$x->value = 1000; //this is 1000 JUST inside this function
}
$example = new Example;
$example->value = 0;
test1($example); // $example->value changed to 1
test2($example); // $example did NOT changed to a new object
// $example->value is still 1
?>
Use this for functions when you wish to simply alter the original variable and return it again to the same variable name with its new value assigned.
function add(&$var){ // The & is before the argument $var
$var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
Actually both methods are valid but it depends upon your requirement. Passing values by reference often makes your script slow. So it's better to pass variables by value considering time of execution. Also the code flow is more consistent when you pass variables by value.
A PHP reference is an alias, allowing two different variables to write to the same value.
And in PHP, if you have a variable that contains an object, that variable does not contain the object itself. Instead, it contains an identifier for that object. The object accessor will use the identifier to find the actual object. So when we use the object as an argument in function or assign it to another variable, we will be copying the identifier that points to the object itself.
https://hsalem.com/posts/you-think-you-know-php.html
class Type {}
$x = new Type();
$y = $x;
$y = "New value";
var_dump($x); // Will print the object.
var_dump($y); // Will print the "New value"
$z = &$x; // $z is a reference of $x
$z = "New value";
var_dump($x); // Will print "New value"
var_dump($z); // Will print "New value"
Depends on the version, 4 is by value, 5 is by reference.

Function to Round Variable Values - PHP [duplicate]

Are PHP variables passed by value or by reference?
It's by value according to the PHP Documentation.
By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference.
To have an argument to a function always passed by reference, prepend an ampersand (&) to the argument name in the function definition.
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>
In PHP, by default, objects are passed as reference to a new object.
See this example:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj->abc = 30;
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30
Now see this:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.
Now see this:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue(&$obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.
I hope you can understand this.
It seems a lot of people get confused by the way objects are passed to functions and what passing by reference means. Object are still passed by value, it's just the value that is passed in PHP5 is a reference handle. As proof:
<?php
class Holder {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
function swap($x, $y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
a, b
To pass by reference means we can modify the variables that are seen by the caller, which clearly the code above does not do. We need to change the swap function to:
<?php
function swap(&$x, &$y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
b, a
in order to pass by reference.
http://www.php.net/manual/en/migration5.oop.php
In PHP 5 there is a new Object Model. PHP's handling of objects has been completely rewritten, allowing for better performance and more features. In previous versions of PHP, objects were handled like primitive types (for instance integers and strings). The drawback of this method was that semantically the whole object was copied when a variable was assigned, or passed as a parameter to a method. In the new approach, objects are referenced by handle, and not by value (one can think of a handle as an object's identifier).
PHP variables are assigned by value, passed to functions by value and when containing/representing objects are passed by reference. You can force variables to pass by reference using an '&'.
Assigned by value/reference example:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
output:
var1: test, var2: final test, var3: final test
Passed by value/reference example:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
output:
var1: foo, var2 BAR
Object variables passed by reference example:
class Foo{
public $var1;
function __construct(){
$this->var1 = "foo";
}
public function printFoo(){
print $this->var1;
}
}
$foo = new Foo();
changeFoo($foo);
$foo->printFoo();
function changeFoo($foo){
$foo->var1 = "FOO";
}
output:
FOO
(The last example could be better probably.)
You can pass a variable to a function by reference. This function will be able to modify the original variable.
You can define the passage by reference in the function definition:
<?php
function changeValue(&$var)
{
$var++;
}
$result=5;
changeValue($result);
echo $result; // $result is 6 here
?>
You can do it either way.
Put an '&' symbol in front and the variable you are passing becomes one and the same as its origin i.e. you can pass by reference, rather than make a copy of it.
so
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
TL;DR: PHP supports both pass by value and pass by reference. References are declared using an ampersand (&); this is very similar to how C++ does it. When the formal parameter of a function is not declared with an ampersand (i.e., it's not a reference), everything is passed by value, including objects. There is no distinction between how objects and primitives are passed around. The key is to understand what gets passed along when you pass in objects to a function. This is where understanding pointers is invaluable.
For anyone who comes across this in the future, I want to share this gem from the PHP docs, posted by an anonymous user:
There seems to be some confusion here. The distinction between pointers and references is not particularly helpful.
The behavior in some of the "comprehensive" examples already posted can be explained in simpler unifying terms. Hayley's code, for example, is doing EXACTLY what you should expect it should. (Using >= 5.3)
First principle:
A pointer stores a memory address to access an object. Any time an object is assigned, a pointer is generated. (I haven't delved TOO deeply into the Zend engine yet, but as far as I can see, this applies)
2nd principle, and source of the most confusion:
Passing a variable to a function is done by default as a value pass, ie, you are working with a copy. "But objects are passed by reference!" A common misconception both here and in the Java world. I never said a copy OF WHAT. The default passing is done by value. Always. WHAT is being copied and passed, however, is the pointer. When using the "->", you will of course be accessing the same internals as the original variable in the caller function. Just using "=" will only play with copies.
3rd principle:
"&" automatically and permanently sets another variable name/pointer to the same memory address as something else until you decouple them. It is correct to use the term "alias" here. Think of it as joining two pointers at the hip until forcibly separated with "unset()". This functionality exists both in the same scope and when an argument is passed to a function. Often the passed argument is called a "reference," due to certain distinctions between "passing by value" and "passing by reference" that were clearer in C and C++.
Just remember: pointers to objects, not objects themselves, are passed to functions. These pointers are COPIES of the original unless you use "&" in your parameter list to actually pass the originals. Only when you dig into the internals of an object will the originals change.
And here's the example they provide:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}
?>
I wrote an extensive, detailed blog post on this subject for JavaScript, but I believe it applies equally well to PHP, C++, and any other language where people seem to be confused about pass by value vs. pass by reference.
Clearly, PHP, like C++, is a language that does support pass by reference. By default, objects are passed by value. When working with variables that store objects, it helps to see those variables as pointers (because that is fundamentally what they are, at the assembly level). If you pass a pointer by value, you can still "trace" the pointer and modify the properties of the object being pointed to. What you cannot do is have it point to a different object. Only if you explicitly declare a parameter as being passed by reference will you be able to do that.
Variables containing primitive types are passed by value in PHP5. Variables containing objects are passed by reference. There's quite an interesting article from Linux Journal from 2006 which mentions this and other OO differences between 4 and 5.
http://www.linuxjournal.com/article/9170
Objects are passed by reference in PHP 5 and by value in PHP 4.
Variables are passed by value by default!
Read here: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
class Holder
{
private $value;
public function __construct( $value )
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function setValue( $value )
{
return $this->value = $value;
}
}
class Swap
{
public function SwapObjects( Holder $x, Holder $y )
{
$tmp = $x;
$x = $y;
$y = $tmp;
}
public function SwapValues( Holder $x, Holder $y )
{
$tmp = $x->getValue();
$x->setValue($y->getValue());
$y->setValue($tmp);
}
}
$a1 = new Holder('a');
$b1 = new Holder('b');
$a2 = new Holder('a');
$b2 = new Holder('b');
Swap::SwapValues($a1, $b1);
Swap::SwapObjects($a2, $b2);
echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";
echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";
Attributes are still modifiable when not passed by reference so beware.
Output:
SwapObjects: b, a
SwapValues: a, b
Regarding how objects are passed to functions you still need to understand that without "&", you pass to the function an object handle , object handle that is still passed by value , and it contains the value of a pointer. But you can not change this pointer until you pass it by reference using the "&"
<?php
class Example
{
public $value;
}
function test1($x)
{
//let's say $x is 0x34313131
$x->value = 1; //will reflect outsite of this function
//php use pointer 0x34313131 and search for the
//address of 'value' and change it to 1
}
function test2($x)
{
//$x is 0x34313131
$x = new Example;
//now $x is 0x88888888
//this will NOT reflect outside of this function
//you need to rewrite it as "test2(&$x)"
$x->value = 1000; //this is 1000 JUST inside this function
}
$example = new Example;
$example->value = 0;
test1($example); // $example->value changed to 1
test2($example); // $example did NOT changed to a new object
// $example->value is still 1
?>
Use this for functions when you wish to simply alter the original variable and return it again to the same variable name with its new value assigned.
function add(&$var){ // The & is before the argument $var
$var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
Actually both methods are valid but it depends upon your requirement. Passing values by reference often makes your script slow. So it's better to pass variables by value considering time of execution. Also the code flow is more consistent when you pass variables by value.
A PHP reference is an alias, allowing two different variables to write to the same value.
And in PHP, if you have a variable that contains an object, that variable does not contain the object itself. Instead, it contains an identifier for that object. The object accessor will use the identifier to find the actual object. So when we use the object as an argument in function or assign it to another variable, we will be copying the identifier that points to the object itself.
https://hsalem.com/posts/you-think-you-know-php.html
class Type {}
$x = new Type();
$y = $x;
$y = "New value";
var_dump($x); // Will print the object.
var_dump($y); // Will print the "New value"
$z = &$x; // $z is a reference of $x
$z = "New value";
var_dump($x); // Will print "New value"
var_dump($z); // Will print "New value"
Depends on the version, 4 is by value, 5 is by reference.

Passing named parameters to a php function through call_user_func_array

When trying to call a function in a child class with an arbitrary set of parameters, I'm having the following problem:
class Base{
function callDerived($method,$params){
call_user_func_array(array($this,$method),$params);
}
}
class Derived extends Base{
function test($foo,$bar){
print "foo=$foo, bar=$bar\n";
}
}
$d = new Derived();
$d->callDerived('test',array('bar'=>'2','foo'=>1));
Outputs:
foo=2, bar=1
Which... is not exactly what I wanted - is there a way to achieve this beyond re-composing the array with the index order of func_get_args? And yes, of course, I could simply pass the whole array and deal with it in the function... but that's not what I want to do.
Thanks
No. PHP does not support named parameters. Only the order of parameters is taken into account. You could probably take the code itself apart using the ReflectionClass to inspect the function parameter names, but in the end you'd need to use this to reorder the array anyway.
The stock PHP class ReflectionMethod is your friend.
Example:
class MyClass {
function myFunc($param1, $param2, $param3='myDefault') {
print "test";
}
}
$refm = new ReflectionMethod('MyClass', 'myFunc');
foreach ($refm->getParameters() as $p)
print "$p\n";
And the result:
Parameter #0 [ <required> $param1 ]
Parameter #1 [ <required> $param2 ]
Parameter #2 [ <optional> $param3 = 'myDefault' ]
At this point you know the names of the parameters of the target function. With this information you can modify your method 'callDerived', and you can re-order the array to call_user_func_array according to the parameter names.
Good news, I had the same concern (I was looking for named arguments in PHP, like Python does), and found this useful tool : https://github.com/PHP-DI/Invoker
This uses the reflection API to feed a callable with some arguments from an array and also use optional arguments defaults for other parameters that are not defined in the array.
$invoker = new Invoker\Invoker;
$result = $invoker->call(array($object, 'method'), array(
"strName" => "Lorem",
"strValue" => "ipsum",
"readOnly" => true,
"size" => 55,
));
Have fun
UPDATE: PHP 8 Now supports named parameters. And it works with call_user_func_array if you pass an associative array. So you can simply do this:
<?php
function myFunc($foo, $bar) {
echo "foo=$foo, bar=$bar\n";
}
call_user_func_array('myFunc', ['bar' => 2, 'foo' => 1]);
// Outputs: foo=1, bar=2
In your code, you'll be happy to know that you don't have to change a thing. Just upgrade to PHP 8 and it'll work as you expected
You can simply pass an array and extract:
function add($arr){
extract($arr, EXTR_REFS);
return $one+$two;
}
$one = 1;
$two = 2;
echo add(compact('one', 'two')); // 3
This will extract as references, so there is close to no overhead.
I use a bitmask instead of boolean parameters:
// Ingredients
define ('TOMATO', 0b0000001);
define ('CHEESE', 0b0000010);
define ('OREGANO', 0b0000100);
define ('MUSHROOMS', 0b0001000);
define ('SALAMI', 0b0010000);
define ('PEPERONI', 0b0100000);
define ('ONIONS', 0b1000000);
function pizza ($ingredients) {
$serving = 'Pizza with';
$serving .= ($ingredients&TOMATO)?' Tomato':'';
$serving .= ($ingredients&CHEESE)?' Cheese':'';
$serving .= ($ingredients&OREGANO)?' Oregano':'';
$serving .= ($ingredients&MUSHROOMS)?' Mushrooms':'';
$serving .= ($ingredients&SALAMI)?' Salami':'';
$serving .= ($ingredients&ONIONS)?' Onions':'';
return trim($serving)."\n" ;
}
// Now order your pizzas!
echo pizza(TOMATO | CHEESE | SALAMI);
echo pizza(ONIONS | TOMATO | MUSHROOMS | CHEESE); // "Params" are not positional
For those who still might stumble on the question (like I did), here is my approach:
since PHP 5.6 you can use ... as mentioned here:
In this case you could use something like this:
class Base{
function callDerived($method,...$params){
call_user_func_array(array($this,$method),$params);
}
}
class Derived extends Base{
function test(...$params){
foreach ($params as $arr) {
extract($arr);
}
print "foo=$foo, bar=$bar\n";
}
}
$d = new Derived();
$d->callDerived('test',array('bar'=>'2'),array('foo'=>1));
//print: foo=1, bar=2
There is a way to do it and is using arrays (the most easy way):
class Test{
public $a = false;
private $b = false;
public $c = false;
public $d = false;
public $e = false;
public function _factory(){
$args = func_get_args();
$args = $args[0];
$this->a = array_key_exists("a",$args) ? $args["a"] : 0;
$this->b = array_key_exists("b",$args) ? $args["b"] : 0;
$this->c = array_key_exists("c",$args) ? $args["c"] : 0;
$this->d = array_key_exists("d",$args) ? $args["d"] : 0;
$this->e = array_key_exists("e",$args) ? $args["e"] : 0;
}
public function show(){
var_dump($this);
}
}
$test = new Test();
$args["c"]=999;
$test->_factory($args);
$test->show();
a full explanation can be found in my blog:
http://www.tbogard.com/2013/03/07/passing-named-arguments-to-a-function-in-php/

Are PHP Variables passed by value or by reference?

Are PHP variables passed by value or by reference?
It's by value according to the PHP Documentation.
By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference.
To have an argument to a function always passed by reference, prepend an ampersand (&) to the argument name in the function definition.
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>
In PHP, by default, objects are passed as reference to a new object.
See this example:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj->abc = 30;
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30
Now see this:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.
Now see this:
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue(&$obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.
I hope you can understand this.
It seems a lot of people get confused by the way objects are passed to functions and what passing by reference means. Object are still passed by value, it's just the value that is passed in PHP5 is a reference handle. As proof:
<?php
class Holder {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
function swap($x, $y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
a, b
To pass by reference means we can modify the variables that are seen by the caller, which clearly the code above does not do. We need to change the swap function to:
<?php
function swap(&$x, &$y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
b, a
in order to pass by reference.
http://www.php.net/manual/en/migration5.oop.php
In PHP 5 there is a new Object Model. PHP's handling of objects has been completely rewritten, allowing for better performance and more features. In previous versions of PHP, objects were handled like primitive types (for instance integers and strings). The drawback of this method was that semantically the whole object was copied when a variable was assigned, or passed as a parameter to a method. In the new approach, objects are referenced by handle, and not by value (one can think of a handle as an object's identifier).
PHP variables are assigned by value, passed to functions by value and when containing/representing objects are passed by reference. You can force variables to pass by reference using an '&'.
Assigned by value/reference example:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
output:
var1: test, var2: final test, var3: final test
Passed by value/reference example:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
output:
var1: foo, var2 BAR
Object variables passed by reference example:
class Foo{
public $var1;
function __construct(){
$this->var1 = "foo";
}
public function printFoo(){
print $this->var1;
}
}
$foo = new Foo();
changeFoo($foo);
$foo->printFoo();
function changeFoo($foo){
$foo->var1 = "FOO";
}
output:
FOO
(The last example could be better probably.)
You can pass a variable to a function by reference. This function will be able to modify the original variable.
You can define the passage by reference in the function definition:
<?php
function changeValue(&$var)
{
$var++;
}
$result=5;
changeValue($result);
echo $result; // $result is 6 here
?>
You can do it either way.
Put an '&' symbol in front and the variable you are passing becomes one and the same as its origin i.e. you can pass by reference, rather than make a copy of it.
so
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
TL;DR: PHP supports both pass by value and pass by reference. References are declared using an ampersand (&); this is very similar to how C++ does it. When the formal parameter of a function is not declared with an ampersand (i.e., it's not a reference), everything is passed by value, including objects. There is no distinction between how objects and primitives are passed around. The key is to understand what gets passed along when you pass in objects to a function. This is where understanding pointers is invaluable.
For anyone who comes across this in the future, I want to share this gem from the PHP docs, posted by an anonymous user:
There seems to be some confusion here. The distinction between pointers and references is not particularly helpful.
The behavior in some of the "comprehensive" examples already posted can be explained in simpler unifying terms. Hayley's code, for example, is doing EXACTLY what you should expect it should. (Using >= 5.3)
First principle:
A pointer stores a memory address to access an object. Any time an object is assigned, a pointer is generated. (I haven't delved TOO deeply into the Zend engine yet, but as far as I can see, this applies)
2nd principle, and source of the most confusion:
Passing a variable to a function is done by default as a value pass, ie, you are working with a copy. "But objects are passed by reference!" A common misconception both here and in the Java world. I never said a copy OF WHAT. The default passing is done by value. Always. WHAT is being copied and passed, however, is the pointer. When using the "->", you will of course be accessing the same internals as the original variable in the caller function. Just using "=" will only play with copies.
3rd principle:
"&" automatically and permanently sets another variable name/pointer to the same memory address as something else until you decouple them. It is correct to use the term "alias" here. Think of it as joining two pointers at the hip until forcibly separated with "unset()". This functionality exists both in the same scope and when an argument is passed to a function. Often the passed argument is called a "reference," due to certain distinctions between "passing by value" and "passing by reference" that were clearer in C and C++.
Just remember: pointers to objects, not objects themselves, are passed to functions. These pointers are COPIES of the original unless you use "&" in your parameter list to actually pass the originals. Only when you dig into the internals of an object will the originals change.
And here's the example they provide:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}
?>
I wrote an extensive, detailed blog post on this subject for JavaScript, but I believe it applies equally well to PHP, C++, and any other language where people seem to be confused about pass by value vs. pass by reference.
Clearly, PHP, like C++, is a language that does support pass by reference. By default, objects are passed by value. When working with variables that store objects, it helps to see those variables as pointers (because that is fundamentally what they are, at the assembly level). If you pass a pointer by value, you can still "trace" the pointer and modify the properties of the object being pointed to. What you cannot do is have it point to a different object. Only if you explicitly declare a parameter as being passed by reference will you be able to do that.
Variables containing primitive types are passed by value in PHP5. Variables containing objects are passed by reference. There's quite an interesting article from Linux Journal from 2006 which mentions this and other OO differences between 4 and 5.
http://www.linuxjournal.com/article/9170
Objects are passed by reference in PHP 5 and by value in PHP 4.
Variables are passed by value by default!
Read here: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
class Holder
{
private $value;
public function __construct( $value )
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function setValue( $value )
{
return $this->value = $value;
}
}
class Swap
{
public function SwapObjects( Holder $x, Holder $y )
{
$tmp = $x;
$x = $y;
$y = $tmp;
}
public function SwapValues( Holder $x, Holder $y )
{
$tmp = $x->getValue();
$x->setValue($y->getValue());
$y->setValue($tmp);
}
}
$a1 = new Holder('a');
$b1 = new Holder('b');
$a2 = new Holder('a');
$b2 = new Holder('b');
Swap::SwapValues($a1, $b1);
Swap::SwapObjects($a2, $b2);
echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";
echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";
Attributes are still modifiable when not passed by reference so beware.
Output:
SwapObjects: b, a
SwapValues: a, b
Regarding how objects are passed to functions you still need to understand that without "&", you pass to the function an object handle , object handle that is still passed by value , and it contains the value of a pointer. But you can not change this pointer until you pass it by reference using the "&"
<?php
class Example
{
public $value;
}
function test1($x)
{
//let's say $x is 0x34313131
$x->value = 1; //will reflect outsite of this function
//php use pointer 0x34313131 and search for the
//address of 'value' and change it to 1
}
function test2($x)
{
//$x is 0x34313131
$x = new Example;
//now $x is 0x88888888
//this will NOT reflect outside of this function
//you need to rewrite it as "test2(&$x)"
$x->value = 1000; //this is 1000 JUST inside this function
}
$example = new Example;
$example->value = 0;
test1($example); // $example->value changed to 1
test2($example); // $example did NOT changed to a new object
// $example->value is still 1
?>
Use this for functions when you wish to simply alter the original variable and return it again to the same variable name with its new value assigned.
function add(&$var){ // The & is before the argument $var
$var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
Actually both methods are valid but it depends upon your requirement. Passing values by reference often makes your script slow. So it's better to pass variables by value considering time of execution. Also the code flow is more consistent when you pass variables by value.
A PHP reference is an alias, allowing two different variables to write to the same value.
And in PHP, if you have a variable that contains an object, that variable does not contain the object itself. Instead, it contains an identifier for that object. The object accessor will use the identifier to find the actual object. So when we use the object as an argument in function or assign it to another variable, we will be copying the identifier that points to the object itself.
https://hsalem.com/posts/you-think-you-know-php.html
class Type {}
$x = new Type();
$y = $x;
$y = "New value";
var_dump($x); // Will print the object.
var_dump($y); // Will print the "New value"
$z = &$x; // $z is a reference of $x
$z = "New value";
var_dump($x); // Will print "New value"
var_dump($z); // Will print "New value"
Depends on the version, 4 is by value, 5 is by reference.

Categories