Wordpress - Using OOP in themes
Speed
My current base theme has 13 classes. When I build a new theme, I either use these classes as they are or I extend them. That system makes the process of building a new theme very, very fast.
Tight scopes
I rarely need global variables, because everything my code has to know is hidden in class members. So I’m able to share a variable between two very different filters or actions without the risk of collision with poorly written plugins.
Maintenance
Each class is one file. If I need to update a client’s theme, I just update some files. Whatever happens inside the classes is up to me as long as I offer the same API.
An example: above the comment_form();
call, I use a simple action:
do_action( 'load_comment_class' );
comment_form();
Which comment class will be loaded decides my controller. What exactly happens inside the comment class decides the individual class.
Try this with a pure procedural approach and you’re going nuts. :)
Readability
It is so much easier to reread and understand your own code some months later if you have separated everything by its task.
Some examples for useful class hierarchies
Meta_Box
-> extended byShortdesc_Meta_Box
andSimple_Checkbox_Meta_Box
-> extended bySidebar_Switch
User_Profile_Addon
-> extended byUser_Profile_Checkbox
(see Question 3255)Comment_Form
-> extended by{$theme_name}_Comment_Form
I can understand your confusion based on the example you provided. That's really a poor way to use a class ... and just because a class is used, doesn't make a system OOP.
In the case of Hybrid, they're just using a class to namespace their functions. Considering Hybrid is a theme framework, this is done so that child themes can re-use function names without the developer having to worry about name collision. In many cases, a theme framework (parent theme) is so complex, many child theme developers will never understand exactly what goes on under the hood.
If Hybrid didn't use a class structure, child theme developers would need to know what all of the existing function calls were so they could avoid re-using names. And yes, you could just prefix all of your functions with a unique slug, but that makes the code hard to read, hard to maintain, and inherently non-reusable should you develop further systems that want to make use of the same functionality.
To Answer Your Questions
Wtf? What's the point of doing this? Obviously you won't be using two or more instances of the same theme, at the same time.
No, you won't be using two or more instances of the same theme. But like I said, think of the class structure in this case as namespacing the functions, not creating a traditional object instance. Lumping everything together in a class and either instantiating it to call methods (myClass->method();
) or calling methods directly (myClass::method();
) is a very clean way to namespace things in a readable, reusable fashion.
Of course you could always use something like myClass_method();
instead, but if you want to re-use any of this code in another theme, in a plug-in, or in antoher framework you have to go back through and change all of your prefixes. Keeping everything in a class is cleaner and allows you to redevelop and redeploy much more quickly.
Let's assume that the plugins do this for the namespace (which is ridiculous), but what's the theme excuse? Am I missing something?
In the majority of situations I'd agree with you. However, that majority is quickly waning. I host several sites on a MultiSite installation that use variations of the same theme. Rather than re-create the same theme over and over again with minor differences, I have a single "class" for the parent theme and all of the child themes extend that class. This allows me to define custom functionality for each site while still maintaining a general sense of uniformity across the entire network.
On the one hand, theme developers may choose a class-based approach to namespace their functionality (which isn't ridiculous if you work in an environment where you re-use chunks of the same code over and again). On the other hand, theme developers may choose a class-based approach for easy extensibility by child themes.
What's the advantage of coding a theme like this?
If you're only using Hybrid on your site, there's little to know advantage for you as the end user. If you're building a child theme for Hybrid there are advantages from namespacing and extensibility. If you work for ThemeHybrid, the advantage lies in quick, efficient code reuse across your other projects (Prototype, Leviathan, etc).
And if you're a theme developer who likes a specific feature of Hybrid but not the entire theme, the advantage lies in quick, efficient code reuse in your non-Hybrid project (assuming it's also GPL).
Another point to consider: Speed.
if ( !class_exists('cccYourClassName') )
// VERSUS
if ( !function_exists('ccc_your_function_name') )
After a short look/print out i found ~1.700 internal functions and ~1.400 user functions = ~3.100/3.200 functions VS. ~250 Classes. I guess this says the most about how much a look up would need. If you call for !function_exists('')
on about 50-100 functions in your theme... just set a timer for one and then start doing some math. Even if it's not OOP it's a good way to make code
1) reuseable
2) maintainable
3) exchangeable
4) little faster
When you take a look at different classes floating around in the web that help you doing meta boxes, widgets, etc. fast, then it's good to use a controller like @toscho mentioned, because you can just plug classes out and in and just replace some lines in the controller that handles your classes.