Php By Reference - php

Can someone please explain what the "&" does in the following:
class TEST {
}
$abc =& new TEST();
I know it is by reference. But can someone illustrate why and when I would need such a thing? Or point me to a url where this is explained well. I am unable to grasp the concept.
Thank you very much.

As I understand it, you're not asking about PHP references in general, but about the $foo =& new Bar(); construction idiom.
This is only seen in PHP4 as the usual $foo = new Bar() stores a copy of the object. This generally goes unnoticed unless the class stored a reference to $this in the constructor. When calling a method on the returned object later on, there would be two distinct copies of the object in existence when the intention was probably to have just one.
Consider this code where the constructor stores a reference to $this in a global var
class Bar {
function Bar(){
$GLOBALS['copy']=&$this;
$this->str="hello";
}
}
//store copy of constructed object
$x=new Bar;
$x->str="goodbye";
echo $copy->str."\n"; //hello
echo $x->str."\n"; //goodbye
//store reference to constructed object
$x=&new Bar;
$x->str="au revoir";
echo $copy->str."\n"; //au revoir
echo $x->str."\n"; //au revoir
In the first example, $x and $copy refer to different instances of Foo, but in the second they are the same.

Firstly, you don't really need to use it if you are using PHP 5, in PHP 5 all objects are passed by reference by default.
Secondly, when you assign an object to a variable name, either by creation, passing in a parameter, or setting a variable value, you are either doing so by reference or value.
Passing by reference means you pass the actual memory reference for the object, so say you passed an object as a parameter to a function, any changes that function makes to that variable will be reflected in the parent method as well, you are actually changing the state of that object in memory.
The alternative, to pass by value means you pass a copy of that object, not the memory reference, so any changes you make, will not be reflected in the original.

The PHP Manual does a pretty decent job of explaining references.
I should note, that they are NOT the same thing as a pointer or a reference in many other languages, although there are similarities. And as for objects being "passed by reference" by default - that's not exactly true either.
I would recommend reading the manual section first (and probably then re-reading a couple of times until you get it), and then come back here if you still have more questions.

A simpler way to look at it may be like this:
$a = 'foo';
$b = 'bar';
$a =& $b;
$b = 'foobar';
echo $a . ' ' . $b;
will output
foobar foobar

It might be helpful to think of it like this: In PHP, all variables are really some sort of pointer: The entries in the symbol table - the thing which maps variable names to values - contain a zval * in the C implementation of the Zend Engine.
During assignment - this includes setting function arguments - magic will happen:
If you do $a = $b, a copy of the value pointed to by the symbol table entry of $b will be created and a pointer to this new value will be placed in the symbol table entry for $a. Now, $a and $b will point to different values. PHP uses this as its default calling convention.
If you do $a =& $b, the symbol table entry for $a will be set to the pointer contained in the symbol table entry for $b. This means $a and $b now point to the same value - they are aliases of each other with equal rights until they are rebound by the programmer. Also note that $a is not really a reference to $b - they are both pointers to the same object.
That's why calling them 'aliases' might be a good idea to emphasize the differences to C++' reference implementation:
In C++, a variable containing a value and a reference created from this variable are not equal - that's the reason why there are things like dangling references.
To be clear: There is no thing like a reference type in PHP, as all variables are already internally implemented as pointers and therefore every one of them can act as a reference.
PHP5 objects are still consistent with this description - they are not passed by reference, but a pointer to the object (the manual calls it an 'object identifier' - it might not be implemented as an actual C pointer - I did not check this) is passed by value (meaning copied on assignment as described above).
Check the manual for details on the relation between PHP5 objects and references.

Related

What exactly are the entities 'Object', 'Object Reference', 'Object Identifier', 'Object Accessors' in PHP? How they function?

Below is the text from PHP Manual :
PHP treats objects in the same way as references or handles, meaning
that each variable contains an object reference rather than a copy of
the entire object.
A PHP reference is an alias, which allows two
different variables to write to the same value. As of PHP 5, an object
variable doesn't contain the object itself as value anymore. It only
contains an object identifier which allows object accessors to find
the actual object. When an object is sent by argument, returned or
assigned to another variable, the different variables are not aliases:
they hold a copy of the identifier, which points to the same object.
After going through the above text I've following doubts in my mind:
What exactly the 'Object' is?
What exactly the 'Object Reference' is?
What exactly an 'Object Identifier' is?
Does the entity called 'Object Identifier' work implicitly/internally?
How to create a copy of the 'Object Identifier'?
Do the terms 'Object Reference' and 'Object Identifier' mean the same thing?
What exactly the 'Object Accessors' are?
Do the terms 'Instance of a class', 'Instance of an object', 'Object variable', 'Class instance', 'Object instance' mean the same thing? If yes, what these entities indicate? If no, what are the differences in between their meanings?
How all of the above entities function?
Can someone please clear the doubts I have in an easy to understand, simple and lucid language in short and step-by-step manner?
It would be great if someone can explain these concepts with some suitable, working code example having explanatory comments at appropriate places in the code.
If possible, someone can also explain with the help of pictorial representation of working of these concepts. It would be highly appreciated.
You can take up following example or specify your own suitable example to explain all of the above concepts.
<?php
class A {
public $foo = 1;
}
$a = new A;
$b = $a;
$b->foo = 2;
echo $a->foo."\n";
$c = new A;
$d = &$c;
$d->foo = 2;
echo $c->foo."\n";
$e = new A;
function foo($obj) {
$obj->foo = 2;
}
foo($e);
echo $e->foo."\n";
?>
Thank You.
Reference links from the PHP Manual :
https://secure.php.net/manual/en/oop5.intro.php#oop5.intro
https://secure.php.net/manual/en/language.oop5.references.php#language.oop5.references
An Object is an instance of a class that you create with new Classname.
An Object Reference is a PHP variable whose value is an Object.
An Object Identifier is a value internal to the PHP implementation that identifies a particular object. It's probably something like an index into an array that contains pointers to all the objects.
Yes, they're internal, not visible to PHP applications.
Assign a variable containing an object to another variable. Internally, both variables contain copies of the object identifier.
They're not the same thing, but closely related. An object reference is a PHP variable, the object identifier is the internal data that it contains.
Object accessors are operations that access the contents of objects, such as $d->foo.
Yes, they're all essentially synonyms.
This is all just implementation details for how you can have multiple variables referring to the same object without having to use reference variables explicitly.
$a = new A;
$b = $a;
$a->foo = 2;
echo $b->foo; // echoes 2
The assignment isn't making a copy of the object, it's just copying the object identifier. All copies of an object identifier refer to the same object. Think of it like a pointer in languages like C or C++ -- when you copy a pointer, both variables refer to the same memory.
To make a copy of an object, you have to use clone.
$c = clone $a;
This is different from how arrays work, which is that assignment makes a copy, unless you use an explicit reference variable. (As an optimization, PHP uses copy-on-write, so it doesn't actually copy the array memory unless you modify it.)
$x = array(1);
$y = $x;
$z = &$x;
$x[0] = 2;
echo $y[0]; // echoes 1
echo $z[0]; // echoes 2

Why aren't reference operators used in Symfony2?

I've been programming for quite a while with PHP. Recently I decided to try and use a framework. I happened to pick Symfony2. One of the first thing I noticed was that I've never encountered any reference operator(&). I used them frequently in my previous projects.
I've found this on php.net/manual/...
Note that in PHP5 you generally don't need the reference operator -- at all -- when dealing with class objects, because PHP5 implements objects using Instances (which are more like C pointers than PHP's references system).
Are references uncommon in frameworks, or perhaps in general in PHP5?
Edit
I know what references do and how they work. I wonder why the Symfony2 examples on the site do not use reference operators anywhere.
In fact if you use passing object as argument to function, PHP won't create copy of the object but simple points to the same place in memory where this object exists. So there is no need to use reference as long as you don't want to do some complex stuff (point to another object/variable in memory).
You should look at Object and references in PHP manual.
You can also consider the following code:
<?php
class A {
public $x= 20;
}
$a = new A();
echo $a->x."<br />";
change($a);
echo $a->x."<br />";
changeRef($a);
echo $a->x."<br />"; // you get notice in this line. $a is no longer A object
echo $a."<br />";
function change(A $b) {
$b->x = 10;
$b = 15;
}
function changeRef(A &$b) {
$b->x = 10;
$b = 15;
}
I've created 2 function change (without reference) and changeRef (with reference).
As you see when using change function even if we don't use reference, when using property assignment inside function also property of variable $a has been changed - it's because $a and $b pointed to the same place in memory. However if inside the same function I set any other object (in this case simple int) to variable $b, nothing more happened. Simple $b is now pointing to some other place in memory where 15 was placed but $a is pointing to the same place in memory as earlier.
However in send function (with reference) after assigning $b value 15 it means that $a has been also assigned the same value ($b is reference to $a) so after running this function when you try to display property of $a it's impossible no more (warning raised) because $a is no longer A object but simple int with 15 value.
I hope this clears you this issue a bit and now you understand why references don't need to be used very often when using objects.
EDIT
As you mentioned using references for arrays, PHP uses copy-on-write mechanism. So if you pass array to function or other variable as long as you don't modify it no copy will be created even if passing arrays as argument.
Consider the following code:
$arr = [1,2,3];
show($arr);
function show($a) {
foreach ($a as $item) {
echo $item;
}
}
in above case no copy of $arr will be created so there is no need to use reference in this case. So unswerving your question if you don't have to modify the array you don't need to use reference. Probably that's why Symfony doesn't use references in that cases.
In addition references make code less clear because if you don't go to function declaration you won't know that it could modify your data. So probably that's the extra reason they are not so commonly used.
Passing by Reference
Note: There is no reference sign on a function call - only on function definitions. Function definitions alone are enough to correctly pass the argument by reference. As of PHP 5.3.0, you will get a warning saying that "call-time pass-by-reference" is deprecated when you use & in foo(&$a);. And as of PHP 5.4.0, call-time pass-by-reference was removed, so using it will raise a fatal error.

Is there ambiguity in the way "reference" is used?

For example, in PHP we can write something like this:
class C {
var $x;
function __construct($x) {
$this->x = $x;
}
function __toString() {
return (string)$this->x;
}
}
function f1($obj) {
$obj->x = 2;
}
$a = new C(1);
f1($a);
echo $a; // 2
And some would say that this indicates objects are passed by reference, because you can modify their properties and those changes are reflected outside of the class. i.e., the object is not copied the way primitives are.
But then we can write this:
function f2($obj) {
$obj = new C(2);
}
$b = new C(1);
f2($b);
echo $b; // 1
Which now suggests the object is not passed by reference at all. In reality, the object is copied (i.e., passed by value) but not deep-copied; $obj is copied, but $x still refers to the same thing.
I've heard the word "reference" used to mean both ways; some would say PHP is pass by reference, others would say pass by value.
If we say that PHP is pass by reference, then what do we mean when say define a function like
function f3(&$obj)
? That function takes a reference an to an object, this suggests the first meaning is wrong.
But then what about languages like C++, and structs in C#? My C++ is a bit rusty, but I believe the whole class actually gets deep-copied when pass it around, which is why it's encouraged to make your functions take references if possible, or use pointers. In C# there's a difference between structs and classes in how they get passed.
What do you call this deep-copying behaviour, if not pass by value?
It seems we have 3 behaviours and only two phrases to describe them, and this is creating a lot of confusion in the community.
Heck, I'm just waiting for one of you to tell me I wrote something wrong here.
In summary, the 3 behaviours are:
Objects are deep-copied (the object and its properties are cloned)
Only the object is copied (its properties still refer to the same chunk of memory)
The object is not copied at all
Technically, what should we call each of these behaviours? pass-by-???
First things first: You might want to read References Explained.
Normally, variables are always passed by value. What matters is what the value actually is.
If the variable "holds an object", it holds a reference to the object.
Thus, when you have a function definition like
function foo($bar) {}
a reference to the object is passed. That is why you can change the object.
But if you assign a new value to the variable inside the function, then you are just overwriting the reference with something else and you loose the reference to the object.
So assuming you have a variable $someVar that you pass to the function, $bar and $someVar will have the same value (namely a reference), but they have their own location in memory.
Before:
$someVar -> object_reference ┐
├ -> object
$bar -> object_reference ┘
After:
$someVar -> object_reference -> object
$bar -> other_value
Now, if the function definition is like
function foo(&$bar) {}
then you are actually passed a reference to the location in memory of some other variable.
If you call the function with foo($someVar), $bar will point to the same location as $someVar, i.e. if you assign a new value, you are overwriting that particular location in the memory.
Before:
$someVar ┐
├ -> object_reference -> object
$bar ┘
After:
$someVar ┐
├ -> other_value object
$bar ┘
If I had my druthers, the term "object reference" in .net would be replaced by something like "object-id", to make clear that in most cases when an object is passed to a routine, the object-id is passed by value (though there are some cases, like Dictionary.TryGetValue, where an object-id is passed by reference). Using the same term to describe an object-id and a type of parameter passing leads to confusion.
In C++, the first two are both called pass-by-value. How deep a deep copy occurs depends on the copy semantics of the class in question, which can and should be specified by the programmer (some classes are handles to resources and must be shallow-copied; others, such as most containers, must be deep-copied). Python has library functions for deep and shallow copying. Deep copying is sometimes called cloning, esp. in C++ and Java.
The third is called pass by reference. This is the general term for passing something that can be modified in-place by the callee.
(C is an exception to this convention, since it has no notion of reference, but pass-by-pointer is almost the same as pass-by-reference.)
There are two things you have to differentiate... references to variables and references to objects. As long as you don't assign an other value to the parameter $obj, you are dealing with the exact same object as outside of the function. After assigning an other object to it, the variable has changed but since you only passed a reference to the object and not one to the variable, the variable on the outside is still untouched pointing to your original object...

In PHP can someone explain cloning vs pointer reference?

To begin with, I understand programming and objects, but the following doesn't make much sense to me in PHP.
In PHP we use the & operator to retrieve a reference to a variable. I understand a reference as being a way to refer to the same 'thing' with a different variable. If I say for example
$b = 1;
$a =& $b;
$a = 3;
echo $b;
will output 3 because changes made to $a are the same as changes made to $b. Conversely:
$b = 1;
$a = $b;
$a = 3;
echo $b;
should output 1.
If this is the case, why is the clone keyword necessary? It seems to me that if I set
$obj_a = $obj_b then changes made to $obj_a should not affect $obj_b,
conversely $obj_a =& $obj_b should be pointing to the same object so changes made to $obj_a affect $obj_b.
However it seems in PHP that certain operations on $obj_a DO affect $obj_b even if assigned without the reference operator ($obj_a = $obj_b). This caused a frustrating problem for me today while working with DateTime objects that I eventually fixed by doing basically:
$obj_a = clone $obj_b
But most of the php code I write doesn't seem to require explicit cloning like in this case and works just fine without it. What's going on here? And why does PHP have to be so clunky??
Basically, there are two ways variables work in PHP...
For everything except objects:
Assignment is by value (meaning a copy occurs if you do $a = $b.
Reference can be achieved by doing $a = &$b (Note the reference operator operates upon the variable, not the assignment operator, since you can use it in other places)...
Copies use a copy-on-write tehnique. So if you do $a = $b, there is no memory copy of the variable. But if you then do $a = 5;, the memory is copied then and overwritten.
For objects:
Assignment is by object reference. It's not really the same as normal variable by reference (I'll explain why later).
Copy by value can be achieved by doing $a = clone $b.
Reference can be achieved by doing $a = &$b, but beware that this has nothing to do with the object. You're binding the $a variable to the $b variable. It doesn't matter if it's an object or not.
So, why is assignment for objects not really reference? What happens if you do:
$a = new stdclass();
$b = $a;
$a = 4;
What's $b? Well, it's stdclass... That's because it's not writing a reference to the variable, but to the object...
$a = new stdclass();
$a->foo = 'bar';
$b = $a;
$b->foo = 'baz';
What's $a->foo? It's baz. That's because when you did $b = $a, you are telling PHP to use the same object instance (hence the object reference). Note that $a and $b are not the same variable, but they do both reference the same object.
One way of thinking about it, is to think of all variables which store an object as storing the pointer to that object. So the object lives somewhere else. When you assign $a = $b where $b is an object, all you're doing is copying that pointer. The actual variables are still disjoint. But when you do $a = &$b, you're storing a pointer to $b inside of $a. Now, when you manipulate $a it cascades the pointer chain to the base object. When you use the clone operator, you're telling PHP to copy the existing object, and create a new one with the same state... So clone really just does a by-value copy of the varaible...
So if you noticed, I said the object is not stored in an actual variable. It's stored somewhere else and nothing but a pointer is stored in the variable. So this means that you can have (and often do have) multiple variables pointing to the same instance. For this reason, the internal object representation contains a refcount (Simply a count of the number of variables pointing to it). When an object's refcount drops to 0 (meaning that all the variables pointing to it either go out of scope, or are changed to somethign else) it is garbaged collected (as it is no longer accessable)...
You can read more on references and PHP in the docs...
Disclaimer: Some of this may be oversimplification or blurring of certain concepts. I intended this only to be a guide to how they work, and not an exact breakdown of what goes on internally...
Edit: Oh, and as for this being "clunky", I don't think it is. I think it is really useful. Otherwise you'd have variable references being passed around all over the place. And that can yield some really interesting bugs when a variable in one part of an application affects another variable in another part of the app. And not because it's passed, but because a reference was made somewhere along the line.
In general, I don't use variable references that much. It's rare that I find an honest need for them. But I do use object references all the time. I use them so much, that I'm happy that they are the default. Otherwise I'd need to write some operator (since & denotes a variable reference, there'd need to be another to denote an object reference). And considering that I rarely use clone, I'd say that 99.9% of use cases should use object references (so make the operator be used for the lower frequency cases)...
JMHO
I've also created a video explaining these differences. Check it out on YouTube.
In Short:
In PHP 5+ objects are passed by reference. In PHP 4 they are passed by value (that's why it had runtime pass by reference, which became deprecated). So, you have to use the clone operator in PHP5 to copy objects:
$objectB = clone $objectA;
Also note that it's just objects that are passed by reference, not other variables. The following may clear you up more:
PHP References
PHP Object Cloning
PHP Objects and References
i've written a presentation to explain better how php manage memory with its variables:
https://docs.google.com/presentation/d/1HAIdvSqK0owrU-uUMjwMWSD80H-2IblTlacVcBs2b0k/pub?start=false&loop=false&delayms=3000
take a look ;)

Are there pointers in php?

What does this code mean? Is this how you declare a pointer in php?
$this->entryId = $entryId;
Variable names in PHP start with $ so $entryId is the name of a variable.
$this is a special variable in Object Oriented programming in PHP, which is reference to current object.
-> is used to access an object member (like properties or methods) in PHP, like the syntax in C++.
so your code means this:
Place the value of variable $entryId into the entryId field (or property) of this object.
The & operator in PHP, means pass reference. Here is a example:
$b=2;
$a=$b;
$a=3;
print $a;
print $b;
// output is 32
$b=2;
$a=&$b; // note the & operator
$a=3;
print $a;
print $b;
// output is 33
In the above code, because we used & operator, a reference to where $b is pointing is stored in $a. So $a is actually a reference to $b.
In PHP, arguments are passed by value by default (inspired by C). So when calling a function, when you pass in your values, they are copied by value not by reference. This is the default IN MOST SITUATIONS. However there is a way to have pass by reference behaviour, when defining a function. Example:
function plus_by_reference( &$param ) {
// what ever you do, will affect the actual parameter outside the function
$param++;
}
$a=2;
plus_by_reference( $a );
echo $a;
// output is 3
There are many built-in functions that behave like this. Like the sort() function that sorts an array will affect directly on the array and will not return another sorted array.
There is something interesting to note though. Because pass-by-value mode could result in more memory usage, and PHP is an interpreted language (so programs written in PHP are not as fast as compiled programs), to make the code run faster and minimize memory usage, there are some tweaks in the PHP interpreter. One is lazy-copy (I'm not sure about the name). Which means this:
When you are coping a variable into another, PHP will copy a reference to the first variable into the second variable. So your new variable, is actually a reference to the first one until now. The value is not copied yet. But if you try to change any of these variables, PHP will make a copy of the value, and then changes the variable. This way you will have the opportunity to save memory and time, IF YOU DO NOT CHANGE THE VALUE.
So:
$b=3;
$a=$b;
// $a points to $b, equals to $a=&$b
$b=4;
// now PHP will copy 3 into $a, and places 4 into $b
After all this, if you want to place the value of $entryId into 'entryId' property of your object, the above code will do this, and will not copy the value of entryId, until you change any of them, results in less memory usage. If you actually want them both to point to the same value, then use this:
$this->entryId=&$entryId;
No, As others said, "There is no Pointer in PHP." and I add, there is nothing RAM_related in PHP.
And also all answers are clear. But there were points being left out that I could not resist!
There are number of things that acts similar to pointers
eval construct (my favorite and also dangerous)
$GLOBALS variable
Extra '$' sign Before Variables (Like prathk mentioned)
References
First one
At first I have to say that PHP is really powerful language, knowing there is a construct named "eval", so you can create your PHP code while running it! (really cool!)
although there is the danger of PHP_Injection which is far more destructive that SQL_Injection. Beware!
example:
Code:
$a='echo "Hello World.";';
eval ($a);
Output
Hello World.
So instead of using a pointer to act like another Variable, You Can Make A Variable From Scratch!
Second one
$GLOBAL variable is pretty useful, You can access all variables by using its keys.
example:
Code:
$three="Hello";$variable=" Amazing ";$names="World";
$arr = Array("three","variable","names");
foreach($arr as $VariableName)
echo $GLOBALS[$VariableName];
Output
Hello Amazing World
Note: Other superglobals can do the same trick in smaller scales.
Third one
You can add as much as '$'s you want before a variable, If you know what you're doing.
example:
Code:
$a="b";
$b="c";
$c="d";
$d="e";
$e="f";
echo $a."-";
echo $$a."-"; //Same as $b
echo $$$a."-"; //Same as $$b or $c
echo $$$$a."-"; //Same as $$$b or $$c or $d
echo $$$$$a; //Same as $$$$b or $$$c or $$d or $e
Output
b-c-d-e-f
Last one
Reference are so close to pointers, but you may want to check this link for more clarification.
example 1:
Code:
$a="Hello";
$b=&$a;
$b="yello";
echo $a;
Output
yello
example 2:
Code:
function junk(&$tion)
{$GLOBALS['a'] = &$tion;}
$a="-Hello World<br>";
$b="-To You As Well";
echo $a;
junk($b);
echo $a;
Output
-Hello World
-To You As Well
Hope It Helps.
That syntax is a way of accessing a class member. PHP does not have pointers, but it does have references.
The syntax that you're quoting is basically the same as accessing a member from a pointer to a class in C++ (whereas dot notation is used when it isn't a pointer.)
To answer the second part of your question - there are no pointers in PHP.
When working with objects, you generally pass by reference rather than by value - so in some ways this operates like a pointer, but is generally completely transparent.
This does depend on the version of PHP you are using.
You can simulate pointers to instantiated objects to some degree:
class pointer {
var $child;
function pointer(&$child) {
$this->child = $child;
}
public function __call($name, $arguments) {
return call_user_func_array(
array($this->child, $name), $arguments);
}
}
Use like this:
$a = new ClassA();
$p = new pointer($a);
If you pass $p around, it will behave like a C++ pointer regarding method calls (you can't touch object variables directly, but that's evil anyways :) ).
entryId is an instance property of the current class ($this)
And $entryId is a local variable
Yes there is something similar to pointers in PHP but may not match with what exactly happens in c or c++.
Following is one of the example.
$a = "test";
$b = "a";
echo $a;
echo $b;
echo $$b;
//output
test
a
test
This illustrates similar concept of pointers in PHP.
PHP passes Arrays and Objects by reference (pointers). If you want to pass a normal variable Ex. $var = 'boo'; then use $boo = &$var;.
PHP can use something like pointers:
$y=array(&$x);
Now $y acts like a pointer to $x and $y[0] dereferences a pointer.
The value array(&$x) is just a value, so it can be passed to functions, stored in other arrays, copied to other variables, etc. You can even create a pointer to this pointer variable. (Serializing it will break the pointer, however.)

Categories