If you’re just starting out as a developer, and you’re learning PHP through WordPress, you might be intimidated by the idea of object-oriented programming (OOP), but the reality is you’ve probably already seen it in use.
For example, have you ever retrieved the ID of a current post like this:
global $post; $id = $post->ID;
That’s object-oriented programing. You might not know the terminology, but what you’ve done in the first line is get the current post as an object of the standard class. In the second line you get the value of that class’s property ID.
Another example of where you’ve probably seen object-oriented PHP is when using WP_Query.
Here is a common use of WP_Query:
$args = array( 'post_type' => 'clothing', 'tag' => 'hat' ); $query = new WP_Query( $args ); if ( $query->have_posts() ) { echo '<ul>'; while ( $query->have_posts() ) { $query->the_post(); echo '<li>' . get_the_title() . '</li>'; } echo '</ul>'; }
It’s actually a fairly advanced use of OOP. I’ll come back to explain what’s going on here on a technical level, after I’ve explained a few things about how OOP works.
Before We Begin
When following along in this article, it’s important that you try out the various examples provided. While you could do this in a theme template file in a test site, it’s quicker and easier to use the debug console that’s made available by an add-on to the excellent Debug Bar plugin.
If you haven’t already started using Debug Bar, you really should. It’s an essential development tool that can be installed separately or as part of the Developer plugin bundle. Debug Bar gives you lots of great tools, and has several add-ons.
One of my favorites (and the one you should install) is Debug Bar Console. I know this plugin hasn’t been updated for so long that it has a warning on WordPress.org, but trust me it works just fine in every version of WordPress I’ve used — including 4.0.
Debug Bar Console gives you a place to quickly test PHP and MySQL in the context of your current site configuration. If you haven’t already installed it, go ahead and do so now, you’ll thank me later.
Methods vs Functions
In functionality programming, we’re used to working with functions — which once they are declared are always available. In OOP, functions inside a class are called methods. Methods are only accessible in the context of that class.
When using non-object oriented PHP in your themes or plugins, you call a function directly and prefix the function names with a unique slug to avoid conflicts with other plugins or themes.
Keep in mind that you should still prefix class names to avoid conflicts with other themes or plugins. When using OOP, methods — or functions inside classes — do not need to be prefixed, since they are unique to that class. However, you also need to access them through the class. To understand this in your console, let’s create two classes. Both will have just one method — the class name — which will echo the name of the class. Here are the two classes, hat and shoe:
class hat { function class_name() { return "hat"; } } class shoe { function class_name() { return "shoe"; } }
As you can see in each class there’s a method called class name, which returns a string. These two methods have the same name. That’s not an issue since they are in two different classes. In order to use them, we must first instantiate each class, and place them in a variable. We do this by setting a variable equal to a new instance of the class, like this:
$hat = new hat(); $shoe = new shoe();
To test this, echo the class_name method from each class, like this:
echo $hat->class_name(); echo $shoe->class_name();
Play around in the console a bit with these two classes. Try adding different methods to the classes. Keep in mind that methods always need to be accessed in the context of a class. If you want to access a method of a class inside another method in that class, you use the variable “$this,” as-in “this class” to access it.
Here is a simple class that has two methods.
One gets a post object and tests that it is valid. The other checks if that object is from a post in one of several post types.
class clothing_post_types { function get_post ( $id ) { $post = get_post( $id ); //check if $post is an object of the stdClass if ( is_object( $post) && is_a( 'stdClass' ) ) { return $post; } } function check_post_type( $id ) { //get post object $post = $this->get_post( $id ); //check that $this->get_post didn't return false (ie invalid post ID was used) if ( $post ) { //get post type $post_type = $post->post_type(); if ( in_array( $post_type ), array( 'hat', 'shoe', 'shirt' ) ) { return true; } } } }
Properties vs Variables
One of the biggest limitations of procedural programming (the opposite of OOP — not using classes) is how difficult it is to share variables between functions. This leads to using global variables, which is an overkill.
In a class, you can share a variable inside the class. We call this the class variable properties.
Remember before when we looked at the global post object? In that example we were working with class properties. In the console, take a look at a post object, again, like this:
$post = get_post( 1 ); print_r( $post );
This should show you the post object for the “Hello World” post that every WordPress site starts with. You’ll see that with the ID property we used before — you have properties for the post content, post type, and more. You can access the properties like this:
$post->ID;
Using Hooks in Classes
Outside of a class, we follow this pattern to hook a function to a WordPress action or filter:
add_action( 'hook', 'callback' ); function callback() { //do something }
When hooking a class method to a WordPress filter or array, you must provide the context for the callback function. This is done by using an array containing an instance of the class and the method name. This is usually done inside of a “magic” method in your class called “__construct().”
Yep, that’s right, OOP has a set of magic methods. And the magic method __construct() is run whenever your class is instantiated. This makes it a perfect place to use add_action and add_filter to hook class methods to WordPress hooks. Since it’s in the class, you can use the variable $this as the class object.
Let’s take a look at a typical use of this in a class:
class add_elements { function __construct() { add_action( 'wp_footer', array( $this, 'inline_script' ) ); add_filter( 'the_content', array( $this, 'end_of_post_message' ) ); } function inline_script() { echo " //add javascript here "; } function end_of_post_method( $content ) { $message = _('Text to output at end of every post'); $content = $content.$message; return $content; } }
More Fun with __construct()
As I said in the previous section, __construct() runs when the class is instantiated. This means that if you want a class to run its methods in a specific order, and pass data between them based on the results of those methods, you can set that up inside __construct(). This is very useful if you’re using a class to run a series of functions that use each other’s output.
Of course, you may want to pass some data into the class when you instantiate it so that the object you build will be based on specific data. In fact, this is exactly what’s going on when you create new WP_Query object, like I showed in the opening paragraph of this article.
If you take a look at the __construct() method in WP_Query, you will see that the first thing the class does is check that that array of arguments isn’t empty, and then it passes it to another class method. That starts a string of events that sets the properties of the class, and allows you to use the class methods to access posts based on the arguments you set.
Your Orientation is Complete
I hope that through this article I’ve been able to effectively introduce you object-oriented PHP by explaining what it is and what it has to offer. Though it’s important to keep in mind, that we’ve only just scratched the surface of what it can do.
Hopefully you can use this article as a stepping stone to kickstart your journey to becoming an OOP master!
Any questions?
13 Comments