Introduction to Object-Oriented PHP for WordPress Developers

Our goal today is introduce object-oriented programming in PHP, as the basis to discuss OOP in WordPress.

In WordPress, object-oriented PHP is a well-known learning challenge. I remember my first attempt to learn WP_Query and WP_Widget, two object-oriented WordPress systems: it took hours, and it was extremely mind-bending and difficult. The issue was that I didn’t understand the core concepts of object-oriented programming both systems were based upon.

So our goal today is to help you get your head around object-oriented PHP (“OO PHP”), as the foundation for a discussion on object-oriented programming (OOP) in WordPress. Luckily, the fundamentals you need to know don’t depend on WordPress or even PHP in any way, so this article will put you well on your way to understanding not just object-oriented WordPress systems like WP_Query and WC_Product, but one of the most powerful programming concepts in existence: OOP itself.

What Object-Oriented Programming Is

OOP gives us the ability to group together a set of properties and behaviors into an entity, or object.

Whether in PHP or any other language, object-oriented programming does one simple thing: it gives us the ability to group together a set of properties and behaviors into an entity, or object.

How Object-Oriented PHP Looks: A Code Example

The main body of this article explains the core intuitions of OOP. So that that doesn’t get too abstract, will start with a code example. Below is a basic example of how object-oriented PHP code looks, whether in WordPress or in another PHP-based environment.

You don’t need to understand the code below right now, but by the end of the article you will. Here it is:

class Dog {
    public $color;
    private $noiselevel;

    public function bark() {
        if( $this->noiselevel === 'loud' ) :
                echo 'BARK';
        else :
                echo 'arf';
        endif;
    }
}

$fido = new Dog;
$fido->color = 'brown';
echo $fido->color; // prints out "brown"
$fido->bark(); // prints out "arf"

Cool, right? (Or: Weird, right?) Again, don’t worry about understanding the above just yet. It’s good just to have some of these “code shapes” in mind as we take a non-coding approach to explaining the key principles of OOP—starting with the most important one, objects.

Before that, a friendly plug: If you like the writing style in this article, you can learn all of WordPress development this way in our acclaimed course Up and Running.

The Best Way to Learn WordPress Development

Get Up and Running Today!

Up and Running is our complete “learn WordPress development” course. Now in its updated and expanded Third Edition for 2018, it’s helped hundreds of happy buyers learn WordPress development the fast, smart, and thorough way.

Here’s what one of them has to say:

“Other courses I’ve tried nearly always lack clear explanations for why WordPress does things a certain way, or how things work together. Up and Running does all of this, and everything is explained clearly and in easy-to-understand language.” -Caroline, WordPress freelancer

Now, onto objects in OO PHP!

Understanding Objects in OOP

Objects are the key to OOP itself, and understanding objects is the key to understanding OOP. Fortunately, our minds work in objects anyway!

The entire pattern of OOP builds from the realization that we humans relate most easily to objects, not “primitives” like colors and movements. In other words, we see “lion running toward me,” not “smear of yellow moving southward.” (There may have been folks who saw the second thing, but they quickly became a smear of red getting dragged northward, and so we rarely hear about them.)

And so, without me needing to try, when I look around the room my brain reports things like “chair,” “person,” “dog,” “carpet,” and “wall.” If you think about that for a minute, it’s actually a miracle: our brains just casually do this! Computers don’t, and that is one of the most profound speed bumps that we humans have had in trying to teach computers to think and work like us.

This may sound abstract or even philosophical, but let’s stay here for a minute, because you’ll need to understand what objects are—without code—to really understand object-oriented code itself.

An Object Has Properties and Methods

Our minds organize the world into objects based on two sets of attributes: the objects’ properties (what they “are”) and behaviors (what they “do”).

  1. A property is a statement about what an object is, such as “a raindrop is made of water.” In OOP, we call properties by this same name: properties.
  2. A behavior is something an object does, such as “a raindrop falls from a cloud.” In OOP, we call behaviors by a slightly different name: methods.

Just like in real life, in OOP an object is a combination of properties and methods. To choose another example: a drinking glass has some properties, such as “made of glass,” and some methods—things it can do—such as “hold liquids.”

A plastic cup is an object, but it is not “an object of type drinking glass”: it’s able to hold liquids, but it’s missing a property (made of glass) that all drinking glasses have.

And a glass shard is an object, but it is not “an object of type drinking glass”: it’s made of glass, but it’s missing a method (hold liquids) that all drinking glasses have.

Think about this for some other real-life objects around you. As basic as this sounds, it is most of the key to understanding the incredible power of object-oriented programming.

What OOP Replaces: Procedural Programming

Okay, so OOP thinks in objects. Why is that good, and what’s the alternative?

For the most part, what OOP replaces is procedural programming: code organized as a set of “do this now” instructions that are not based on an understanding of things as objects.

In other words, procedural code doesn’t say object-oriented things like “pedal the bicycle.” Rather, it says things like “press right metal shape forward 20 degrees.” Just that instruction.

What about the notion that, when we press that shape forward, there’s an actual bicycle that’s being pedaled? That notion definitely lives in the programmer’s mind, and it might live in comments within the code, but it’s not in the code itself.

As odd as it may sound, the bulk of WordPress is written procedurally.

As odd as it may sound, the bulk of WordPress is written procedurally. For example, to display a navigation menu in your theme, you use a function, wp_nav_menu(), that asks you a bunch of questions (in the form of function arguments to pass in), but that never mentions that there’s a thing called a menu that you’re working with. It works all right, but it’s a little—well, procedural.

So the core thing that procedural code lacks, and that OOP gives us, is the ability to usefully group our code into entities—objectsthat we find it easier to think about. We want to work with, for example, actual Users—not just unique “user IDs” that we need to remember are related to a whole bunch of specific bits of stuff in our database. For that, we need OOP.

What Classes Are in OOP, and How they Relate to Objects

In OO PHP, each object arises from a class.

In most programming languages, PHP included, each object arises from a class. If “object” is the most important word in object-oriented PHP, “class” is definitely the second most important. You could even rename “object-oriented PHP” to “doing things with classes and objects in PHP” and you wouldn’t miss much at all.

So, what are classes?

In OOP, you can think of a class as a blueprint for objects. Just like a house blueprint explains the properties and methods of a living house to be constructed from it—but is not itself a house—a class explains the properties and methods of any living object made from it, while not itself being one of those objects.

Let’s see this in action with a bit of code:

class Dog {
    // Properties and methods of the Dog class
}

This is how we declare our class. Notice that the class name, Dog, starts with a capital letter: this is customary to better tell between classes and functions. It’s also customary in WordPress to separate multiple-word class names with underscores, like: My_Long_Class. This is why the WP_Query or WP_Widget classes look the way they do. This is less common in PHP projects outside of WordPress, where MyLongClass (without the underscores) is more conventional.

Creating Objects that are Members of a Class

In OO PHP, you write classes, and then you work with objects that are members of those classes. The process by which this transition occurs is the new keyword. To see that in action, let’s return to our code example:

class Dog {
    // Properties and methods of the Dog class
}

$fido = new Dog; // Let's create an actual Dog object: a member of the Dog class

And boom:

Is that starting to make sense? In PHP, I create an actual object of class Dog with the command new Dog;. And it’s the same pattern for any other class, whether Squirrel, Tennis_Ball, or, more usefully, an OOP WordPress class like WP_Query. We’re on our way!

OOP Vocabulary: Instances and Instantiation

We’re now in a position to tackle some abstract OOP language: “instance” and “instantiate.” Here’s how those terms work in OOP:

  • An instance of a class is simply an object that is a member of that class.
  • To instantiate an object simply means to create it, according to the blueprint that its class lays out.

In PHP, we instantiate objects with the keyword new. When we write $fido = new Dog; then we’ve just instantiated our first instance of the Dog class. We can then instantiate a second Dog object, $spot, as follows: $spot = new Dog; Once we’ve done that, we now have two instances, Fido and Spot, both of them objects that are members of the class Dog.

Instances Vary From Each Other According to their Properties

Within a class, instances vary from one another, but they vary according to the blueprint laid out by the class. All dogs have fur (the $color property), but some are black and some are brown. All dogs bark (the bark() method), but some are louder and some are quieter based on another property (the $noiselevel property). And so on.

And so our two Dog objects, $fido and $spot, are both instances of their underlying class, Dog. Their different values for a Dog‘s properties cause them to behave differently—but all within the parameters laid out by the blueprint of the Dog class itself.

How Object Properties and Methods Look in OO PHP Code

We’ve covered objects, classes, properties, and methods. How do they look in code?

OO PHP Properties

Let’s start with properties, and bring back in a bit of our code example:

class Dog {
    public $color;
}

$fido = new Dog; // Instantiate $fido, an object of class Dog
$fido->color = 'brown'; // We're setting the $color property of $fido to equal "brown"
echo $fido->color; // When we ask what color $fido is, we get back "brown"

As you can see, Fido’s “color” property is simply a variable: $color. This is true across OOP: an object’s properties are simply its internal variables. We can set that variable to be “brown”—only for Fido, not for any other Dogs—with $fido->color = 'brown';

OO PHP Methods

To see how methods look in OO PHP, let’s bring back another piece of our code:

class Dog {
    private $noiselevel;

    public function bark() {
        if( $this->noiselevel === 'loud' ) :
                echo 'BARK';
        else :
                echo 'arf';
        endif;
    }
}

$fido = new Dog;
$fido->bark(); // prints out "arf"

As you can see, Fido’s “bark” method is really a PHP function: bark(). This is true across OOP: an object’s methods are simply the functions defined internally to its class.  So we can make Fido bark by saying, simply, $fido->bark(); Cool, right?

Unlike properties, methods do not change between different instances of a class, nor do they change over the lifecycle of an object. Fido’s “color” property may be different from Spot’s, but their “bark” method will always be identical, and they’ll share that method with all other Dog objects.

But here’s the really cool part: how the bark() method actually behaves depends on another property of Fido himself: his $noiselevel. Since Fido’s $noiselevel property has never been set to "loud", Fido’s bark will print out as a simple “arf.” If something did set Fido’s $noiselevel to "loud", then the behavior of the bark() method would change for Fido, and Fido’s bark would print out as a loud “BARK.” The method doesn’t change between two instances of the Dog class, but how the method actually behaves can change based on what particular values each instance’s properties take.

Arrows Point to an Object’s Properties and Methods

One piece that’s definitely new in the code above is the syntax, especially that arrow, ->. How should we read that?

When referring to an object’s properties or methods in PHP, you’ll always use that arrow, ->. So for any instance of class Dog that I’ve instantiated, for example $spot, I call its bark() method as follows: $spot->bark(). If I want to ask what Spot’s color is, I retrieve that information by simply asking $spot->color.

This arrow syntax is what differentiates properties and methods from their non-OOP counterparts: variables and functions.

Also notice a slight syntax inconsistency here: inside a class, properties like color have a $ before them, but when referenced after a -> they don’t. So writing $spot->$color is wrong, as much sense as it might seem to make. Just something to get used to.

The $this Keyword in OOP

There’s another piece of new syntax above: the $this keyword. Here’s the line we saw it on:

if( $this->noiselevel === 'loud' ) :

Where did $this come from? It’s from the following rule:

  • If you’re working with an instance of an object, outside the code that defines that object’s class, then you reference that instance with its name: $objectname->property or $objectname->method().
  • If you’re writing the code that defines the class itself, then you reference the objects whose blueprint you’re writing with $this$this->property or $this->method().

So the line above asks the following, from within the class: “I want to define this Dog instance’s bark() method, and to do that I need to know its noiselevel property.” We’re in the class itself—writing a blueprint rather than working with a real Dog instance—and so that’s why we ask for $this->noiselevel.

Privacy in OOP: Private vs Protected vs Public

Sometime, you’ll want a class’s methods and properties to be accessible only inside the class itself—that is, accessible to $this calls, but not to $object ones. Let’s see how that looks in our example above:

class Dog {
    public $color;
    private $noiselevel;
}

$fido = new Dog;
$fido->color = 'brown'; // Public property, so we can set it this way
$fido->noiselevel = 'loud'; // THIS WON'T WORK! ERROR TIME

Because noiselevel is a private method of class Dog, manually setting it for our $fido instance won’t work.

Why would we want this? Let’s imagine a method, notice_postman(), that we haven’t included in our demo above:

class Dog {
    public $color;
    private $noiselevel;

    public function notice_postman() {
        $this->noiselevel = 'loud';
    }

    public function bark() {
        if( $this->noiselevel === 'loud' ) :
                echo 'BARK';
        else :
                echo 'arf';
        endif;
    }
}

$fido = new Dog;
$fido->notice_postman(); // This public method changes the private $noiselevel property
$fido->bark(); // Prints "BARK"

Let’s say we only want our Dogs to get loud when they notice the postman. In that case, we make the method public—meaning that I can write $fido->notice_postman(); and it’ll work properly—but we keep the property itself private, so I can’t mess with Fido’s noise level directly. That ensures that, no matter what other code is out there, every Dog‘s $noiselevel property is only getting changed in the way specified in the class blueprint, and that’s when notice_postman() is called.

As you see above, in PHP you set properties and methods to be public or private simply by writing public or private before them. You should always specify these elements for clear code, but the default if you don’t specify them is that everything is public.

There’s also a third privacy status in PHP, protected, that relies on a concept called class inheritance that we’ll cover later.

Returning to Our Object-Oriented PHP Code Example

In this article, we’ve explained the core intuitions of OOP. You should now be able to understand the OO PHP code below, top to bottom.

class Dog {
    public $color;
    private $noiselevel;

    public function bark() {
        if( $this->noiselevel === 'loud' ) :
                echo 'BARK';
        else :
                echo 'arf';
        endif;
    }
}

$fido = new Dog;
$fido->color = 'brown';
echo $fido->color; // prints out "brown"
$fido->bark(); // prints out "arf"

First, we instantiate our class itself, Dog.

On the next two lines we declare the properties $color and $noiselevel, marking them public and private respectively. Finally, we define a public bark() method, which prints out different text depending on the value of that $noiselevel property.

That ends the class definition. Then we make an instance of our Dog class, $fido. We set Fido’s color to brown and then echo that value, which prints out “brown.” Finally, we call the public bark() method on the $fido object, which (since $fido`‘s private $noiselevel property is not set to 'loud') prints out “arf.”

OOP and WordPress: A Great Match

WordPress is a very old software project. A lot of it was written by people who weren’t totally sold on object-oriented PHP, or during a time in which object-oriented programming wasn’t yet the de facto standard for high-quality code. As such, the object-oriented WordPress systems that do exist are in an environment of a lot of other WordPress code that isn’t object-oriented.

But some parts of WordPress are object-oriented, and they’re important: from widgets to WP_Query to the REST API, and also including just about everything in a number of important WordPress software extensions such as WooCommerce.

And in your own code—for example, in custom plugins—you should feel very free to write all the object-oriented code you’d like. After all, it’s how our minds actually work. This introduction to OO PHP is a foundation both for reading and interacting with WordPress OOP systems, and for writing your own.

Thanks for reading!


2 Responses

Comments

  • Christian Saborio says:

    I have just started working with OOP in WordPress and only wish I had started doing so a lot sooner. I’m revisiting most of the spaghetti code I had written and making classes from it. Makes it so much easier to use, understand, and test!

    Your article is beautifully written and makes absolute sense – keep up the amazing work! 🙂

  • John Dee says:

    Great intro to OOP. Another really important reason to be doing OOP in WordPress is to make your code testable. WordPress is eating the internet. It’s high time WP devs learn basic development and software skills. The platform and the user base is just WAITING for you to make something great! wp-bdd.com

Add a Comment

Your email address will not be published. Required fields are marked *