PHP Object Hierarchies

Ever since I wrote the first draft of the Widgets plugin, I've had a fetish for structuring data as object hierarchies in PHP. There is so much you can do with such tiny snippets of code, why wouldn't you want to represent things that way? Some minds call it "too complicated" while others, like mine, consider it the peak of simplicity.

It is a more common design pattern than you might think. If you are using Firefox with the DOM browser, you can see just such a hierarchy in every single page you view on the web. Each node, from little ones like <em>this</em> and <a href="http://w3.org">this</a&gt; to the one that encompasses the entire application window, is an object with a class and methods and attributes and children.

Nobody saw the first draft of the Widgets plugin except myself and Matt. The basic idea was to start with a Widget class from which all widgets would derive. Each widget would therefore inherit certain basic methods: get_options, set_options, display_control, display_widget. The benefit of abstracting these methods is that the API can be preserved even while massive changes are made to the implementation. For example, we might want to start storing all widget options together in a single table row instead of one row for each widget. As long as get_options and set_options kept their interfaces, the underlying code could be improved without forcing 3rd-party widget developers to update their code and telling bloggers to update their dozens of widgets.

And that's just the base class. New classes could quickly be written to deal with special needs by extending the Widget class, adding or replacing methods as needed. The first extending class I wrote was a Widget Container class. Its job was to manage its own array of child Widgets. This would be a top-level Widget to contain all of the other widgets, but also as a movable child widget that contained other movable widgets. By replacing the display_widget method with code to wrap and fire the display_widget methods of the child objects, we have a working parent and a simple hierarchy. What is most exciting about this is that you don't need a giant set of nested foreach loops to output the entire widget tree. The top-level container's display_widget method starts the chain reaction and each descendant widget takes care of itself.

Once you have this kind of extensible hierarchy in place, you might as well just get rid of the entire theme and call everything a widget. The body node of the html document is a container widget. Its children are widgets with linear markup whether the CSS aligns them as columns or rows or any other way. The loop is a widget. The sidebar is a widget with many widgets for children. Widgets control their own display on the blog as well as on the widget admin page, so a container could arrange its children horizonally or vertically or any other way allowed by the supported presentation model.

You now have a drag-and-drop markup creation suite that is infinitely extensible: plugins can provide new widgets and containers by defining classes that derive from Widget. PHP lets us find any class by its parentage, so we do away with the registration API functions. All you have to do is define a class that extends Widget and your widget is added to the palette.
I had almost all of this working and the hardest part of the task was picking myself up off the ground after frequent fits of laughter due to the ease and simplicity of the coding. The only thing in this description that wasn't implemented was the display of containers in the admin screen and this was primarily due to the limitations of the javascript toolkit I had chosen for the job. It was going to take several times the effort just to make the containers draggable.

And with that, we decided to go with a more familiar API for widgets, using functions instead of objects, registration instead of auto-discovery, sidebar instead of whole-blog. Perhaps the OO theme will happen some day.