2.2 Memory Management

In PHP 4, when you copy a variable or pass it to a function, you don't transfer the original variable. Instead, you pass a copy of the data stored in the variable. This is known as pass-by-value because you're copying the variable's values and creating a duplicate.

As a result, the new variable is completely disassociated from the original. Modifying one doesn't affect the other, similar to how calling $zeev->setName( ) didn't affect $rasmus in the earlier example.

2.2.1 Object References

Objects in PHP 5 behave differently from other variables. You don't pass them by value, like you do with scalars and arrays. Instead, you pass them by reference. A reference, or object reference, is a pointer to the variable. Therefore, any alterations made to the passed object are actually made to the original.

Here's an example:

$rasmus = new Person;

$rasmus->setName('Rasmus Lerdorf');

$zeev = $rasmus;

$zeev->setName('Zeev Suraski');

print $rasmus->getName( );

Zeev Suraski

In this case, modifying $zeev does change $rasmus!

This is not what occurs in PHP 4. PHP 4 prints Rasmus Lerdorf because $zeev = $rasmus causes PHP to make a copy of the original object and assign it to $zeev.

However, in PHP 5, this command assigns $zeev a reference to $rasmus. Any changes made to $zeev are actually made to $rasmus.

A similar behavior occurs when you pass objects into functions:

function editName($person, $name) {



$rasmus = new Person;

$rasmus->setName('Rasmus Lerdorf');

setName($rasmus, 'Zeev Suraski');

print $rasmus->getName( );

Zeev Suraski

Normally, changes made inside of editName( ) don't alter variables outside of the function, and to update the original object you need to return the modified variable. That's what you need to do in PHP 4.

Since PHP 5 passes objects by reference, changing them inside a function or a method alters the original object. There's no need for you to pass them explicitly by reference or return the modified copy. This action is also referred to as passing an object handle, since "handle" is a synonym of reference or pointer.

Other variable types, including strings and arrays, are still passed by value by default, unless declared otherwise in the function prototype by placing an ampersand (&) before the variable name.

This change in PHP 5 makes it much easier to use objects because it's far more common to need to pass objects by reference than by value. When your data is encapsulated inside of objects, you frequently pass an instance or two to a method and alter the objects inside of the method.

Without this switch, to cleanly propagate these changes back to the original instances you must place ampersands everywhere you need PHP to pass the objects by reference. However, if you omit even a single ampersand, you end up with a bug that's difficult to isolate and broken code.

To copy the data inside an object and not just the reference to it, instead of a direct assignment using an equals sign (=), use the clone operator:

$rasmus = new Person;

$rasmus->setName('Rasmus Lerdorf');

$zeev = clone $rasmus;

$zeev->setName('Zeev Suraski');

print $rasmus->getName( );

print $zeev->getName( );

Rasmus Lerdorf

Zeev Suraski

This tells PHP not to assign a reference, but to duplicate the values stored in $rasmus and store them in a new object that gets assigned to $zeev. This also means $ramsus and $zeev are independent entities, so calling $zeev->setName( ) doesn't update $rasmus.

PHP 4 programs that rely heavily on PHP 4's pass- and copy-by-value behaviors can enable the zend.ze1_compatibility_mode configuration directive. This causes PHP 5 to clone objects instead of using a reference.

This directive also re-enables a few quirks of PHP 4 that have been ironed out in PHP 5. For instance, you can no longer cast an object to an integer or floating-point number. In PHP 4, objects with properties become 1 and objects without properties become 0.

Turning on the compatibility mode may ease your transition to PHP 5, but it should not be a long-term solution. It reduces application portability, and you cannot share code between applications that enable the compatibility mode and those that assume it's disabled. New sites should be developed with this directive set to its default (Off).

2.2.2 Garbage Collection

Some languages, most notably C, require you to explicitly request memory from the computer whenever you create strings or data structures. Once you've allocated the memory, you can then store information in the variable.

You're also responsible for releasing, or freeing, the memory when you're finished using the variable. This allows the machine to provide the memory to other variables in your program and prevents your computer from running out of RAM. This is also a big pain.

PHP handles memory allocation for you. When you instantiate an object, it automatically doles out memory. When it's deleted, it frees the memory.

The process of cleaning up unused objects is known as garbage collection. The type of garbage collection used by PHP is called reference counting.

When you create a value?such as a string, number, or object?PHP records its existence and sets a counter to one, indicating that there's one copy of the value. From then on, PHP tracks the value, incrementing and decrementing its counter accordingly.

The counter goes up by one when you create a reference to the value, either by passing it into a function by reference or by assigning it by reference to another variable. (Objects are always assigned by reference, unless you use clone; non-objects are assigned by reference using the =& operator.) The counter goes down by one when you remove a reference to a value, which happens when you exit a function or delete the variable. For example:

$rasmus1 = new Person( );  // New object:         Reference count = 1

$rasmus2 = $rasmus1;      // Copy-by-reference:  Reference count = 2

unset($rasmus1);          // Delete a reference: Reference count = 1

sendEmailTo($rasmus);     // Pass-by-reference:  

                          // During function execution:

                          //                     Reference count = 2 

                          // After function completes:

                          //                     Reference count = 1 

unset($rasmus2);          // Delete a reference: Reference count = 0

When the counter hits zero, PHP knows the object is no longer used anywhere in your program, so deletes it and releases its memory. Before it does that, however, PHP calls your object's destructor to let you clean up any higher-level resources you've opened in the object.

At the end of a script, PHP cleans up all the remaining values that still have a nonzero reference count.