Practical OOP for WordPress Installment 1: Objects

This is the first of an ongoing series whose goal is to teach Object Oriented Programming to WordPress developers.  Check out the table of contents for the list of other installments.

This first installment starts off slow and easy to ensure we don’t loose anyone. But fear not, future installments will accelerate the pace and challenge all but the most advanced OOP gurus in the WordPress community.

You’re already using OOP with $post

You may not realize it, but if you are modifying PHP in themes and/or writing plugins you are already using OOP.  The global $post variable is itself an Object.

content-front-page.php
The theme template file content-front-page.php from WordPress’ Twenty Seventeen theme.

Maybe you have yet to directly use $post but you have almost certainly used it indirectly. The template tags (a.k.a. PHP functions) have_posts(), the_post(), get_post_format(), comments_open(), get_comments_number(), comments_template() and the_post_navigation() found in the template below all create, update and/or access the global $post variable:

single.php
The theme template file single.php from WordPress’ Twenty Seventeen theme. Reformatted for presentation purposes.

Understanding $post as object

WordPress functions frequently assume that there is a global variable named $post because WordPress’ bootstrapping code ensures the variable exists with a valid value inside every theme template file (except for within the 404 template, for hopefully obvious reasons.) And that is why functions like get_post_format() and the_post_navigation() are able to assume a global $post variable exists.

In addition, the_post() function of The Loop ensures that $post is continually updated for an archive page.

The global $post variable typically contains a value of type 'object' although at times$post may contain a value of null if a plugin or theme tries to load a post that does not exist (which often indicates a bug, but not always.) 

Assuming you create a Page in WordPress ($post_type==='page') that uses the following page template you will see that this page outputs the word object:

<?php
// Template Name: Output 'type' of $post
global $post;
echo gettype( $post );  // Outputs: object

Code Snippet #1: Using gettype() to inspect
the data type of an object variable.

Objects vs. other variable types

Variables that contain Object values differ from variables that contain other values, such as values of type String, Integer, Float or Boolean. Objects instead contain a collection of contained values, each of which themselves have their own type.

Actually objects are very similar to Arrays in the respect that both arrays and objects contain multiple values.  To illustrate lets compare to the use of an array, using a code pattern with which you might already be familiar:

$post_id = wp_insert_post( array(
   'post_type'   => 'post',
   'post_status' => 'publish',
   'post_title'  => 'Practical Object-Oriented Programming...',
));

Code Snippet #2: Using an array() to pass
arguments to wp_insert_post().

We can of course represent that same information as an object instead. Interestingly wp_insert_post() will accept either an array or an object. For example the following is functionally identical to the previous code:

$post_obj = (object) array(
   'post_type'   => 'post',
   'post_status' => 'publish',
   'post_title'  => 'Practical Object-Oriented Programming...',
); 
$post_id = wp_insert_post( $post_obj );

Code Snippet #3: Using an (object)array() cast
to pass arguments to wp_insert_post().

Here we used a PHP language feature known as casting which converts  (a.k.a “casts”) a value of type array to type object instead. And this is a very convenient way to create object some of the time.

But there is a more explicit way to create an object in PHP and that is with the new statement.

Creating new objects

The more flexible way to create an object is to use the new statement.  The new statement allows you to specify the name of a Class for the object you want, but let us not worry about the specifics of classes just yet; we’ll cover them in our next installment of this Practical OOP for WordPress series.

To create a value of type 'object' you can reference stdClass which has been included in PHP since the earliest days and simply prefix it with new to create an object:

$post_obj = new stdClass();

Code Snippet #4: Creating a new
object of class stdClass

The object created with new stdClass is an empty object, one without any contained values.  It is equivalent to calling (object) array().

Object literals?

Note that unlike arrays, there is no literal syntax for creating an object besides, of course, specifying a literal array() and then casting it to object. Which is what we did in code snippet #3.

Accessing an object’s contained values

Once you have a new object you can add contained values to it using the “pointer” syntax (at least that is what I call it as there does not seem to be an official name.) 

The pointer syntax is a dash followed by a greater-than (->), and in practice is written like this:

$object->value_name

Code Snippet #5: Syntax for access an
object’s contained values.

Updating the object’s contained values

Using the pointer simple variable assignment syntaxes let’s assign values to our $post_obj:

$post_obj = new stdClass();
$post_obj->post_type = 'post'; 
$post_obj->post_status = 'publish'; 
$post_obj->post_title = 'Practical Object-Oriented Programming...'; 
$post_id = wp_insert_post( $post_obj );

Code Snippet #6: Assigning values to a stdClass object
before passing to wp_insert_post().

Note that the above code is functionality identical to code snippets #2 and #3.

The properties of an object

I have shown you the contained values of an object — which are more correctly referred to as “properties” of a object — include a classification not so ironically called a “Class.”  And the one example seen this far has been named stdClass.

In addition an object also has zero or more contained values, and these contained values has a special name in OOP; they are called Properties (see what I did there?)

Looking back at the properties we’ve added to our $post_obj variable thus far include post_type, post_status and post_content.  And we can both assign/set and access/get those properties, i.e.:

/* 
 * Assignment: Sets `post_type` to the literal value 'post'.
 */
$post_obj->post_type = 'post';    

/* 
 * Accessing: Gets `post_type` property and assigns to $post_type.
 */
$post_type = $post_obj->post_type 

Code Snippet #7: Assigning and accessing
values of an object.

Revisiting the $post object

Back to the $post object.

Earlier we saw that $post is updated by The Loop in a theme template, and that many template tags in WordPress(a.k.a. PHP functions) recognize and interact with this $post object.

We also saw a very similar object $post_obj which is much like $post as both have the properties  post_type, post_status and post_content.  Let’s go ahead and look at the properties of a $post object.

Drop the following into new theme template, assign it to a page, and then “view” that page:

<?php 
// Template Name: Display properties of $post
echo '<ul>';
foreach( $post as $property_name => $value ):
    echo "<li>{$property_name}</li>";
endforeach;
echo '</ul>';

Code Snippet #7: Code to output the
properties of the
$post object.

Your page output should contain the list of property names available in the $post object, i.e. $post->ID and $post->guid are both valid property name references:

- ID                                                         
- post_author                                                
- post_date                                                  
- post_date_gmt                                              
- post_content                                               
- post_title                                                 
- post_excerpt                                               
- post_status                                                
- comment_status                                             
- ping_status                                                
- post_password                                              
- post_name                                                  
- to_ping                                                    
- pinged                                                     
- post_modified                                              
- post_modified_gmt                                          
- post_content_filtered                                      
- post_parent                                                
- guid                                                       
- menu_order                                                 
- post_type                                                  
- post_mime_type                                             
- comment_count                                              
- filter                                                     

The $post object’s class

One additional things you’ll learn about our $post_obj object from code snippets #2, #3, #4 and #6 is that they are each fundamentally different from the$post object in code snippets #1 and #7.  In the former the object’s class is stdClass and for the latter it is WP_Post.

Unlike the generically-named stdClass — which is built into PHP — there is actually a PHP source code file in WordPress core that defines the properties of a WP_Post classWhat classes are for and how to define them is a topic for the next installment of this series.

Not that the WordPress core files that define the WP_Post class also define that classes methods, but what methods are and how we’ll use them will need to wait for a future post.

On the other hand, if you are anxious to peek inside you can find the code that defines WP_Post in the following file within your WordPress installation:

/wp-includes/class-wp-post.php                                      

Lesson review

So what did we learn in this first installment?

  1. You are already using OOP (to an extent) with the $post object.
  2. WordPress core automatically makes the $post object available inside theme template files.
  3. The $post object is also updated by the_post() function of The Loop when in multi-post pages such as index.php and any archive templates.
  4. Many template tags aka PHP functions such as the_title()the_content() and next_post_link() assume a $post variable exists and that it contains a valid value.
  5. Calling gettype( $post ) normally will return a string value of 'object' but at times may return 'NULL'.
  6. Both arrays and objects can be empty, and they can also group a collection of one or more contained values.
  7. You can create an object by casting an array to an object using the casting syntax of (object) array( ... ).
  8. You can also create an object using the new statement.
  9. When using the new statement you must specify a Class name.
  10. The default class name in PHP is stdClass and has been part of PHP since the early days.
  11. When first created with new an object of class stdClass contains no values.
  12.  You assign/set and access/get the contained values of an object using (what I call) the “pointer” syntax: $object->value_name = $value; and$value = object->value_name;, respectively.
  13. The contained values of an object are called Properties in OOP terminology.
  14. The properties  of WordPress’ ubiquitous $post object are ID, post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt, post_status, comment_status, ping_status, post_password, post_name, to_ping, pinged, post_modified, post_modified_gmt, post_content_filtered, post_parent, guid, menu_order, post_type, post_mime_type, comment_count and filter.
  15. That same $post object is creating from a class named WP_Post.
  16. The WP_Post class used to creates the $post object also contains something called Methods.
  17. The code defining WP_Post can be found in /wp-includes/class-wp-post.php.
  18. And finally, we’ll learn more about PHP Classes and Class Methods in the next and a future installment of this Practical OOP for WordPress series, respectively.

Leave a Reply

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