Home

PHP 5 references fun: clone for PHP4.

Aug 25, 2004

An issue that's popped up recently in Drupal is PHP5 compatibility. At first, this looks like a no-brainer. Drupal does not use any advanced OO features, so most code runs on both PHP4 and PHP5.

There is a however a nasty change in PHP5: objects are now always passed by reference. Variables hold a handle to the object rather than the object itself. This brings PHP more in line with other OO languages (like Java) and removes some of the ugly from PHP OO code, but it also means that objects are treated differently from all the other types. Old code that depends on having objects copied when not passed by reference will break.

Fixing this is tricky. PHP5 gives you the clone keyword to copy objects with:

<?php
  $copy
= clone $object;
?>

And surprise, surprise, PHP4 does not consider this to be valid code. It doesn't even parse, so you couldn't enclose this with a version check. To get around this, you need a rather ugly hack.

The following code works the same as the above, in PHP5:

<?php
  $copy
= clone($object);
?>

PHP 4 on the other hand will think clone() is a function. The obvious next step is to conditionally declare this function if PHP4 is running. The only problem there is that the function definition will not parse in PHP5 because clone is a special keyword. To get around that, we have to use eval() to postpone parsing. Here's the finished hack:

<?php
 
if (version_compare(phpversion(), '5.0') < 0) {
    eval(
'
    function clone($object) {
      return $object;
    }
    '
);
  }
?>

In PHP5, the native clone keyword will clone the object, while in PHP4 the cloning will happen when the object is passed by value to clone().

We still need to go over the Drupal code and check for reference problems, but at least now we can clone objects consistently.

Cound't we try to avoid relyi

Aug 26, 2004 Gerhard

Cound't we try to avoid relying on copying the object instead?
Where does this come into play?
Gerhard

But we could. It would be a r

Sep 02, 2004 Anonymous

But we could. It would be a really big change though. We could use arrays instead of objects because these obecjts are only another form of associative arrays.

Here is an issue which produced a bug in php5 because of passing by reference.

cross post about a possible fix

Sep 07, 2004 Jason Vogel

http://www.xoops.org/modules/newbb/viewtopic.php?topic_id=21225&forum=8

Way 2
$obj = new MyClass();
$obj_clone = $obj->__clone();

Xoops should use Way 2, as it will work with PHP 4

Can't you just also change

Jan 17, 2005 Anonymous

Can't you just also change the name of the function to make it parse in PHP5? Like copy($object) instead of clone($object).

No

Jan 17, 2005 Steven

The idea is to use PHP5's cloning mechanism through the clone construct, while using the "passing objects by value" cloning mechanism for PHP4.

If we have a function on both versions, then nothing gets cloned on PHP5, as PHP5 objects are always references, even when passed by value.

__clone() method

Jan 17, 2005 Steven

This requires you to cast every object to a class that has the __clone() method defined.

Thanks

Jan 19, 2005 Anonymous

Thank you. This all has been very helpfull :).

hack

Jun 27, 2005 Anonymous

...and php5 complains about __clone()
I used
$obj_clone = unserialize(serialize($obj);
and this is guaranteed to work on php3,4,5 but is slower than 'clone' and '__clone'.

__sleep() __wakeup()

Jan 03, 2006 Anonymous

That method could cause problems if __sleep() and __wakeup() do anything special.

Specifically, if __sleep() serializes references to objects, and __wakeup() re-instnatiates those objects anew, then the references will point to new objects, not the original objects.

Thank You

Jun 30, 2006 Mark O'Sullivan

I am the developer of Vanilla, a web discussion forum that is entirely built using OO in PHP. When PHP 5 was released, I had a few small bugs cropped up in the application. I soon discovered that this was the exact problem.

I found this entry after hours of tearing my hair out trying to figure out a way around the problem. I just wanted to say thank you.

PHP_Compat

Nov 13, 2006 Axel Christ

The PEAR package PHP_Compat also addresses this issue...

here's what made it into

Feb 12, 2007 drewish

here's what made it into Drupal: http://api.drupal.org/api/5/function/drupal_clone

Thanks for the link drewish.

Jun 06, 2007 Dan

Thanks for the link drewish.

Great website btw

Aug 26, 2008 Jamie

Thanks for the clone info, I had not heard of this command until this morning, so this was helpful. Also, your website is really really cool. I have never seen a 3D effect like that before. very nice job! I am going to delicious and stumble you :-)
Jamie

Nice

Oct 17, 2008 Ewen

Nice clean hack - works well on our site.
Thanks!

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <b> <dd> <dl> <dt> <i> <li> <ol> <u> <ul> <img> <em> <p> <br> <span> <div> <h2> <h3> <abbr> <small> <table> <tr> <td> <strong> <acronym> <th> <blockquote>
  • Lines and paragraphs break automatically.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options

Recent comments

Images