On static late binding and proper application design

Recently I’ve decided to “upgrade” my PHP skills to version 5, and redesigned an old website of mine with PHP 5, MySQLi 5, MVC and other things I’ve picked up over the years in mind.

After finishing and attempting to deploy it on an external server I’ve came across a nasty surprise when it turned out that the static late binding feature in general and get_called_class() function in particular does not work on anything prior PHP 5.3. Something which I’ve somehow completely overlooked before… Unfortunately this turned out to be rather difficult to work around without changing much of my design.

During my research into this I’ve encountered a post somewhere in which the author claimed that any design that depends on get_called_class() is probably flawed anyway. Looking at the design goals that it made possible to achieve I do not really agree with that assessment. On the other hand the difficulties I had to go though to make it work on “older” PHP versions made me think about whether this is not indeed a sign that I was doing something wrong…

So below I’ll try to briefly describe what I’ve tried to achieve and I would be grateful if someone could point it out to me if there are any fundamental issues with my approach:

Basically I was trying to avoid repeating code as much as possible. As such I’ve created a Model base class which contained a lot of generic functionality for commonly used database operations. Classes representing the business objects belonging to the individual tables would extend the base class ideally only providing functionality that is unique to the given object.

For many basic operations such as loading, storing and searching the only unique information that is needed is the database table name and in case of the search methods the class name of the objects it needs to fabricate. Therefore the model base class provides a lot of such common functions as searchByFieldValue() etc. As these functions do not rely on instance data they are made static.

To illustrate, let’s take two classes called Article and Comment.
Both provide a “searchAll()” method (and many similar more specialized ones…) e.g. Article::searchAll() and Comment::searchAll()
Both of these will perform a SELECT * on the relevant table, and both will return an array of objects built from the query results. In case of the Article class an array of Article objects and in case of the Comment class an array of Comment objects. Since as mentioned above the only thing that changes is the table name and the class of the fabricated objects it should be reasonable if each of the two classes would need to only provide these two bits of information somehow and leave the rest of the (common) logic to the base class. Therefore searchAll() is provided as a static method in the Model class…

To define which table to query each extended class defines a class constant called DB_TABLE. (Though they could just as well provide a method, it would not change the nature of the problem…) The search etc. functions defined in the base class access this constant to learn the table name. This normally requires the use of get_called_class(). In addition get_called_class() is also used by the search functions to determine what objects to create from the database results…

Without the static late binding functionality the only alternatives are as far as I can see to either provide wrapper functions for each of the functions in the base class in each of the extended classes so that they can “pass down” this information, which seems pretty wasteful, or to only use instance methods and have the constructor pass down the information to the parent classes constructor. However as mentioned before, many of these functions do not require instance data and therefore I don’t see why they cannot be static…

Please let me know if I’m missing some obvious point somewhere, because so far I’m really amazed that it should be this difficult to have common (static) functions factored out into a base class while still retaining the ability to fully use them as if they belonged to the extended class…

I’d just like to say one thing. Many programmers, in their quest for writing DRY code, often abuse basic object-orientated design principles; namely, inheritance. Inheritance wasn’t designed as a means to merely propagate code down to children, as to prevent code repetition. Inheritance was designed to represent a logical object hierarchy, which should begin at the most broad and abstract object, and filter down to the most specific and defined object. Child objects should inherit characteristics of the parent, not necessarily behaviour. For example, an object of type Car may inherit from the object of type MotorVehicle. In such a relationship, the Car object would inherit the characteristics which define a MotorVehicle, such as a motor, and the ability to travel between two points. The MotorVehicle object shouldn’t be responsible for implementing how MotorVehicles get between two points, even if this behaviour is similar between all motor vehicles.

It sounds like what you’ve got, isn’t a proper object relationship. As you said yourself, you’re using a “base” class which seems to have the sole purpose of providing the implementation for common behaviours and actions of child objects. What you should be using instead, is some form of composition.

Well there is nothing wrong with your approach.
One way is not using static method,then this situation wont come and i guess this is what many novice oop pros are doing now

but i know you will want to take advantage of static functions …so it leaves you with the 2 options
1)PHP 5.3 is officially released,so use that …(sometime it may not be in your control)
2)Use the hack methods…like you are doing…(there are many other check php.net user notes)
each has some pros and cons…
i think this will vanish as version progresses…

and may be you will like to have a look in to this as well