Are PHP5 Objects Passed by Reference

Are PHP5 objects passed by reference?

Objects are passed (and assigned) by reference. No need to use address of operator.

Granted what I typed is an oversimplification but will suit your purposes. The documentation states:

One of the key-points of PHP5 OOP that
is often mentioned is that "objects
are passed by references by default".
This is not completely true. This
section rectifies that general thought
using some examples.

A PHP reference is an alias, which
allows two different variables to
write to the same value. As of PHP5,
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.

For a more detailed explanation (explains the oversimplification as well as identifiers) check out this answer.

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.'
?>

PHP 5 | Objects Passed by Reference / Value vs Copy on Write | When added as class property

As the manual page you link to says, the statement "objects are passed by reference" is not a good description of what is happening. A better way to think of it is that the "value" of an object is a handle, pointer, or address to something that exists in a different space.

Whether you assign it to an object property, an array element, or a normal variable, this "value" remains the same, and changes to the object are visible wherever you look at them. Copying the value uses a few bytes (the size of the pointer) but doesn't duplicate the memory of the object itself.

As a final clarification, the "write" in "copy-on-write" refers to modification of an existing value, after copying it from one place to another. So writing $foo = $bar, where $bar is an array, will not duplicate the memory used by the array, but subsequently writing $foo[0]=1; or $bar[0]=1 will, because the two copies need to be distinguished. This doesn't actually come into play in your example; if it did, it would be just the "object pointer" that was copied, so very little extra memory would be needed.

Why are my variables passed by reference?

PHP passes all object by reference, by default.

More informations here : http://php.net/manual/en/language.oop5.references.php

What happens when you pass an object by reference, in php, under the hood?

Any variable that holds an object is not holding the object directly. It holds an identifier of the object. Imagine it as the object living somewhere in an object pool having a number attached to it, e.g. #5. All the variable contains is "object #5". PHP knows that the variable refers to an object and that it's supposed to be object #5.

Whenever you work with such a variable holding an object reference, PHP looks up the referenced object from the object pool.

When you pass such a variable into a function, PHP makes a copy of that reference. There are then two variables holding the content "object #5". Not the object itself has been copied, just this tiny note which says "object #5".

When you pass such a variable into a function by reference, well, you're passing that note "object #5" by reference. PHP won't make a copy of it. But it's still just a variable saying "object #5", so when you're trying to work with it, PHP will look up the object from the pool.

This object reference mechanism is not the same as the & pass-by-reference mechanism. The object reference mechanism works exactly the same as all other pass-by-value operations; it's just that a value which represents a reference to an object is always being treated in a specific way (PHP has to look up the actual object elsewhere).

How do you pass objects by reference in PHP 5?

are you required to use the & modifier to pass-by-reference?

Technically/semantically, the answer is yes, even with objects. This is because there are two ways to pass/assign an object: by reference or by identifier. When a function declaration contains an &, as in:

function func(&$obj) {}

The argument will be passed by reference, no matter what. If you declare without the &

function func($obj) {}

Everything will be passed by value, with the exception of objects and resources, which will then be passed via identifier. What's an identifier? Well, you can think of it as a reference to a reference. Take the following example:

class A
{
public $v = 1;
}

function change($obj)
{
$obj->v = 2;
}

function makezero($obj)
{
$obj = 0;
}

$a = new A();

change($a);

var_dump($a);

/*
output:

object(A)#1 (1) {
["v"]=>
int(2)
}

*/

makezero($a);

var_dump($a);

/*
output (same as before):

object(A)#1 (1) {
["v"]=>
int(2)
}

*/

So why doesn't $a suddenly become an integer after passing it to makezero? It's because we only overwrote the identifier. If we had passed by reference:

function makezero(&$obj)
{
$obj = 0;
}

makezero($a);

var_dump($a);

/*
output:

int(0)

*/

Now $a is an integer. So, there is a difference between passing via identifier and passing via reference.

Are objects in array passed by reference?

Objects are always references, except you clone it explicitly.

You can use spl_object_hash() to retrieve the "object id" and then compare them against each other. Remember, that once an object is removed from the memory by the garbage collector, the ID may get reused.

Are php resources passed by reference?

A resource is not the actual connection. A resource is nothing more than a pointer to a connection. So when you close the connection belonging to this resource, there is no difference in behavior if it was original or a copied one.

Passing by Reference in PHP 5.x

Let's say you want to write a function that removes certain values from an array.

function remove_elements($array, $item1, $item2, ...) {
...
}

You could copy the array and return it. But what if you want to know if anything was removed? Instead you modify the array in-place and return the number of elements removed. So:

function remove_elements(&$array) {
// remove elements
return $number_removed;
}

If you create a complex structure inside your function you may want to return a reference to it rather than a copy of it. But this is a fairly marginal case because PHP uses copy-on-write (ie its not copied until it's modified) but there are some valid use cases.

Returning by reference makes more sense when you're writing a member function of a class. You could return a reference to a data member but this can also break encapsulation.

Lastly, it's worth noting that all objects are passed and returned by reference by default. Everything else is passed and returned by value.

Objects are passed by reference. Parameters to call_user_func aren't. What gives?

Parameters passing

The main issue is - that parameters, passed to call_user_func() will be passed as values - so they will be copy of actual data. This behavior overrides the fact, that

objects are passed by reference. Note:

Note that the parameters for call_user_func() are not passed by
reference.

Tracking error

You're not fully correct about "silent agreement" in such cases. You will see error with level E_WARNING in such cases:


Warning: Parameter 1 to with_ref() expected to be a reference, value given in

So - you will be able to figure out that you're mixing reference and values passing

Fixing the issue

Fortunately, it's not too hard to avoid this problem. Simply create reference to desired value:

class Example {
function RunEvent($event) {
if (isset($this->events[$event])) {
foreach ($this->events[$event] as $k => $v) {

$obj = &$this;
call_user_func($v, $obj);
}
}
}
}

-then result will be quite as expected:


object(Example)#1 (3) {
["events"]=>
array(1) {
["example"]=>
array(2) {
[0]=>
string(8) "with_ref"
[1]=>
string(11) "without_ref"
}
}
["with_ref"]=>
bool(true)
["without_ref"]=>
bool(true)
}


Related Topics



Leave a reply



Submit