PHP OO pitfalls

8 Jan

I should have picked up on this earlier, but PHP does some crazy stuff with objects. Because they’re not objects. Take the following:

  function _init_storage($options) {
    if(!$se = $options['storage_engine']) {
      trigger_error("Error instantiating MetaStash - no storage_engine" );
    }

    $this->engine = $se;
  }

That looks fine, we’ve got some options defined at our constructor and it’s time to connect to a storage engine and blit out (or in) the permanent version of the data. But what if we want to change the storage engine object we were passed — this happens for PBwiki because there’s a notion of the expected place for some data and then the notion of ‘but right now it’s over here’ — as we transition from one storage infrastructure to another we’re going to have several reasonable places to look and the meta information here can indicate the canonical location for the data. So MetaStash calls a change_docroot() on the storage engine to make sure subsequent calls to it will source the right data. Turns out passing in the object as a parameter and assuming it’s treated like a pointer or handle is incorrect. Ugh. Passing an object happens by value – PHP makes a deep copy of the object, so any changes made during that call apply only to the copy.

The corrected code follows:

  function _init_storage($options) {
    if(!$se =& $options['storage_engine']) {
      trigger_error("Error instantiating MetaStash - no storage_engine" );
    }

    $this->engine =& $se;
  }

What galls me is there’s not much warning about this in the docs and apparently no way to detect/trap this behavior at runtime. Ideally I want a development-only check which watches for this but so far no dice.

-Nathan (grumpy)

3 Responses to “PHP OO pitfalls”

  1. Joel Franusic January 8, 2007 at 6:01 pm #

    Here is the diff, if you are like me and have trouble seeing rouge ampersands:

    2c2
    if(!$se =& $options[‘storage_engine’]) {
    6c6
    engine = $se;

    > $this->engine =& $se;

  2. Joel Franusic January 8, 2007 at 6:01 pm #

    Here is the diff, if you are like me and have trouble seeing rouge ampersands:


    2c2
    if(!$se =& $options['storage_engine']) {
    6c6
    engine = $se;
    ---
    > $this->engine =& $se;

  3. Joel Franusic January 8, 2007 at 6:03 pm #

    WHY WORDPRESS? WHY MUST YOU PUNISH ME WITH YOUR COMMENT-MUNGING-HEART-OF-EVIL!?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: