WordPress, a powerful content management system (CMS), allows for extensive customization, particularly through the use of custom post types. WordPress uses posts as a storing method to work with some types of content that need to be stored, changed, and removed. Additionally, the custom post types are used in WordPress to enhance the usability. The idea is that you want to add some functionalities to the WordPress site that are outside of standard WordPress posts. To maintain clean and efficient code, especially when working with multiple custom post types, implementing design patterns such as the Template Method can be incredibly beneficial. This article will explore how the Template Method design pattern can be effectively used to register custom post types in WordPress, ensuring a structured and maintainable approach.
Understanding the Template Method Design Pattern
The Template Method design pattern is a behavioral pattern that defines the skeleton of an algorithm in a parent class, deferring some steps to subclasses without changing the structure of the algorithm. This pattern allows subclasses to redefine specific steps of an algorithm without altering its overall structure. It promotes code reuse and establishes a clear structure for class hierarchies.
The main goal of template method is defining the overall structure of the algorithm, while the subclasses are able to refine, or redefine some parts of the algorithm
The super class in this pattern usually is an abstract class and the steps are implemented by some helper methods which may be either abstract method. When a helper method be an abstract, the subclasses are required to provide concrete implementations in their way.
The invariant portion of the algorithm which somehow guarantees the overarching of the algorithm, is implemented in a method of parent (base) class called template method. The other parts of algorithm that may be vary are implemented in other helper methods of base class. These helper method may have default implementation or not at all (they are abstract methods).
Addition of template method, this pattern has another main part that is subclass of the base class. In fact, the subclasses fill in the variant parts of the algorithm with their specific algorithms.
Subclasses do not override the template method or base class
Template Method pattern is one the use case of inversion of control which in it the high-level code do not define what algorithm to run and low-level codes select which algorithm to run at run-time.
Implementing the Template Method for Custom Post Type in WordPress
In the WordPress, custom post types are registered in constant way but with different configurations. it shows this algorithm has some variant portions and also one fixed part that is a helper function: register_post_type
. Before we go into how to implement the custom post type registration by Template Method pattern, the register_post_type
is introduced. This WordPress helper function is responsible for registration of your own post type. For example while developing your plugin or theme you may need a specific post type like product for an e-commerce website, assignment for an e-learning website, and etc. In this article the custom post type is described by the example of book post type.
It is better to put custom post types in a plugin rather than a theme. This ensures that user content remains portable even if the theme is changed.
The register_post_type
has two parameter that the former is the name of post type that you want to register and the later is the configuration of the registering post type. The post type name as the documentation of WordPress said it do must not be more than 20 characters and all of them should be lowercase, dashes, and underscores. For more detail about the configuration of a post type you can visit this page. Also, the function return the object of registered post type WP_Post_Type
if it is succeeded or WP_Error
on failure situation.
To hook register_post_type
on to the WordPress it must call before admin_init
hook and after after_setup_theme
. The recommended hook is init
.
Now we are ready to register our owned post types with utilizing of Template Method design pattern.
Step 1: Create an Abstract Class
The first step is to define an abstract class that outlines the template method and abstract methods that subclasses must implement. In this case, we create an abstract class Abstract_Post_Type_Register
.
<?php
namespace BookCPT\Post_Types;
abstract class Abstract_Post_Type_Register
{
protected string $post_type;
protected array $args;
abstract protected function init_properties();
public function register()
{
$this->init_properties();
register_post_type($this->post_type, $this->args);
}
public function __construct()
{
add_action('init', [$this, 'register']);
}
}
You can download all codes as a plugin from our GitHub repository.
If you unfamiliar with the namespace and autoloading we recommend you read this article. The Abstract_Post_Type_Register
class contains the register
method, which serves as the template method. Indeed, the register()
method execute WordPress helper function register_post_type()
and as we mentioned before it is the invariant portion of our algorithm. This method calls an abstract method init_properties
that is an abstract method and must be defined by any subclass. In this example the duty of init_properties
is to initialize the parameters of the register_post_type() that are vary for each post type therefore, implemented by subclasses.
The hook method is implemented in the constructor of class that shows where the class is implemented the registration process will be started.
Step 2: Define Concrete Subclasses
Next, we create concrete subclasses that extend the abstract class and provide specific implementations for the abstract method.
<?php
namespace BookCPT\Post_Types;
class Post_Type_Books extends Abstract_Post_Type_Register
{
protected function init_properties()
{
$this->post_type = 'book';
$labels = [
'name' => __('Books', 'text_domain'),
'singular_name' => __('Book', 'text_domain'),
// Additional labels here...
];
$this->args = [
'labels' => $labels,
'public' => true,
// Additional args here...
];
}
public function __construct()
{
parent::__construct();
}
}
In Post_Type_Books
, the init_properties
method is implemented to define the specific properties and arguments for the “book” custom post type.
Step 3: Initialize the Custom Post Types
Finally, we create Install_Post_Types
class responsible for initializing the custom post types and create an instance of this class in our main plugin file.
<?php
namespace BookCPT;
use BookCPT\Post_Types\Abstract_Post_Type_Register;
use BookCPT\Post_Types\Post_Type_Books;
class Install_Post_Types
{
private function create_install_object(Abstract_Post_Type_Register $installClass)
{
return $installClass;
}
public function classes_init()
{
$this->create_install_object(new Post_Type_Books());
}
public function __construct()
{
$this->classes_init();
}
}
The Install_Post_Types
class initializes the custom post type by creating an instance of Post_Type_Books
and invoking its registration process. Let’s describe this class in detail, the Install_Post_Types
class has two public method and one private. The first is create_install_object()
method that get an instance of a class that we want to load in our plugin, as parameter. As the code is shown there is some restriction for the type of parameter and it only accepts the objects that belong to the Abstract_Post_Type_Register
class and finally return this object. Then the classes_init()
method, call the create_install_object()
to install an instance of book post type class. As a result, the class constructor calls the classes_init()
to load all the classes that have been instantiated, until an instance of the Install_Post_Types
class is created in the main plugin file.
Set the Abstract_Post_Type_Register
class as type of parameter helps us to make sure that all post type creator classes inherit from Abstract_Post_Type_Register
class.
In continue, If we want add another post type to this plugin we only need to create a post type class with specific configuration of that post type like following example:
<?php
namespace BookCPT\Post_Types;
class Post_Type_Articles extends Abstract_Post_Type_Register
{
protected function init_properties()
{
$this->post_type = 'article';
$labels = [
'name' => __('Articles', 'text_domain'),
'singular_name' => __('Article', 'text_domain'),
// Additional labels here...
];
$this->args = [
'labels' => $labels,
'public' => true,
// Additional args here...
];
}
public function __construct()
{
parent::__construct();
}
}
Then instantiate it in the Install_Post_Types
class as shown in the following codes:
<?php
namespace BookCPT;
use BookCPT\Post_Types\Abstract_Post_Type_Register;
use BookCPT\Post_Types\Post_Type_Books;
use BookCPT\Post_Types\Post_Type_Articles;
class Install_Post_Types
{
private function create_install_object(Abstract_Post_Type_Register $installClass)
{
return $installClass;
}
public function classes_init()
{
$this->create_install_object(new Post_Type_Books());
$this->create_install_object(new Post_Type_Articles());
}
public function __construct()
{
$this->classes_init();
}
}
Benefits of Using the Template Method Pattern
- Code Reusability: The pattern promotes reuse of the registration logic across different custom post types, reducing redundancy.
- Maintainability: By encapsulating the registration logic within a structured hierarchy, the code becomes easier to manage and maintain.
- Flexibility: New custom post types can be added easily by creating new subclasses without modifying existing code.
Conclusion
Implementing the Template Method design pattern for registering custom post types in WordPress provides a robust framework for managing multiple post types efficiently. It ensures a clear separation of concerns, promotes code reuse, and enhances maintainability. By leveraging this design pattern, developers can streamline their workflow and maintain cleaner, more organized codebases in WordPress projects.
By adopting the Template Method pattern, you can ensure that your custom post types are registered in a consistent and maintainable manner, paving the way for more scalable and manageable WordPress development.