Clearing Up Some Annoying PHP Static

While on vacation I started some prep work for using MongoDB at DailyLit, which is mostly written in PHP.  The prep work consists of creating a lightweight way of getting PHP objects in and out of MongoDB (I know there are some things out there already, but what’s the fun in that?).

Here is a slightly simplified summary what I am shooting for:

class Fruit extends mdbObject { }  // provides all the DB functionality
class Apple extends Fruit { }
$a = new Apple();
$a->mdbInsert();  // insert this instance into the DB
$b = Apple::mdbFindOne();   // get an apple object from the DB
$c = Fruit::mdbFindOne();  // this might be get an Apple or a Banana

I like the idea of using static/class methods for retrieval because these will be generating one or more objects and I do not want to have to deal with separate factory or builder classes.  Unfortunately, I encountered some annoying PHP static:

class Fruit {
   public static function test() {
      echo __CLASS__;
   }
}

class Apple extends Fruit {
}

Apple::test();

This prints “Fruit” — what the flagnard?  For my plan to work, I need this to print “Apple”.

First, lets establish that “Apple” is not an unreasonable expectation.  In Python, I can do the following:

class Fruit:
   @classmethod
   def test(c):
      print c

class Apple(Fruit):
   pass

Apple.test()

This prints “Apple” (well, actually it prints “__main__.Apple”).

In Ruby, I can do this:

class Fruit
  def self.test
      puts self.name
    end
end

class Apple<Fruit
end

Apple.test()

That also prints “Apple”, which suggests that my expectation for the PHP code was reasonable.

Second, is there a solution in PHP? I started to poke around a bit more and discovered “Late Static Bindings.”  The documentation starts very promising:

As of PHP 5.3.0, PHP implements a feature called late static bindings which can be used to reference the called class in a context of static inheritance.

I was, however, taken aback by the examples on that page, which seemed to suggest that in order to get the right version of __CLASS__ you had to actually implement a static method in the derived class that would then be called by the base class, which is exactly what I was trying to avoid in the first place.

Only by reading through the user comments did I discover that there is now also a new function get_called_class() that provides the solution:

class Fruit {
	public static function test() {
		echo get_called_class();
	}	
}

class Apple extends Fruit {
}

Apple::test();

That will print “Apple” (assuming you are running PHP 5.3.0).  It is amazing to me that this only got fixed now.  Then again namespaces only just arrived in that version, so maybe I shouldn’t have been surprised.

Reblog this post [with Zemanta]

Posted: 27th August 2009Comments

Newer posts

Older posts

blog comments powered by Disqus
  1. continuations posted this

Newer posts

Older posts