WordPress has a great system for managing templates, partials and to allow the overwriting of specific files in child themes.
When a new request come to WordPress engine, the CMS first try to guess the needed main template file among a specific hierarchy. This work is done in /wp-includes/template-loader.php
file; then the filter template_include
comes into place to allows developers to customize the default behavior.
Within the main template file (namely single.php, page.php, home.php and such) theme designers can use the famous get_template_part
function to include different template partials based on context.
While this method is quick and functional, it lacks of structure; for example, in template partials it is possible to use variables from the outer scope and that can make hard to follow the program workflow.
Many developers within WordPress community have developed their own method to address this issue, with the aim to make WordPress template system more close to an MVC pattern.
Following a MVC pattern is critical for long-term maintainability of your theme and plugin templates. Far too often logic is mixed with presentation in the WordPress ecosystem.
We at WAGA have included an MVC-like template system component in our WBF framework and for the rest of this article, we’ll brief introduce it.
Our system is not a replacement for WordPress get_template_part()
but more a tool to help you think of a way to separate logic and presentation in your codebase (we heavely use it when output templates through filters or actions callback, such as add_menu_page()
function).
Let’s say you want to output a template that looks like that:
<h1>Hello <?php echo $name; ?>!</h1>
<p>
<?php echo $content; ?>
</p>
You first put it in a separate file, for example called hello.php
. Then you can use our template system:
$v = new \WBF\components\mvc\HTMLView("path/to/hello.php");
$v->display([
'name' => 'John Doe',
'content' => 'You are awesome!'
]);
And that’s it! It is that simple. Your template will be rendered like that:
<h1>Hello John Doe!</h1>
<p>
You are awesome!
</p>
Let’s us make a more meaningful example: this is how (traditionally and “naively”) you can add an admin page to WordPress and display content in it.
add_action('admin_menu', 'foo_add_admin_page');
function foo_add_admin_page(){
add_options_page('My Option Page', 'My Option Page', 'my-capability', 'my-option-page', 'foo_display_option_page');
}
function foo_display_option_page(){
$content = 'This is my option page';
?>
<div class='wrap'>
<h1>My Options</h1>
<?php echo $content; ?>
</div>
<?php
}
You can easily see that while it can works for small functionality, it can be a real pain to maintain when the code grows.
Here it is the WBF approach to the issue (and with a more concise code).
add_action('admin_menu', function(){
add_options_page('My Option Page', 'My Option Page', 'my-capability', 'my-option-page', function(){
$title = 'My Options';
$content = 'This is my option page';
/*
* Here you can do all your logic, data retrieving and elaboration and then pass to the template only the
* the results of all operations.
*/
$v = new \WBF\components\mvc\HTMLView("path/to/view.php");
$v->display([
'title' => $title,
'content' => $content
]);
});
});
<div class='wrap'>
<h1><?php echo $title; ?></h1>
<?php echo $content; ?>
</div>
As you can see, now logic and presentation are two separated aspect and can be maintained more easily.
Of course, WBF MVC component can do much more and can be even extended to support real template engines. One of its strenghts is that it fully support template overwriting, both in themes and in plugins.
For example:
$v = new \WBF\components\mvc\HTMLView("templates/parts/hello.php");
Will look for hello.php
in the following paths:
- your-child-theme/templates/parts/hello.php
- your-parent-theme/templates/parts/hello.php
$v = new \WBF\components\mvc\HTMLView("templates/parts/hello.php","my-plugin");
Will look for hello.php
in the following paths:
- your-child-theme/templates/parts/hello.php
- your-parent-theme/templates/parts/hello.php
- my-plugin-directory/templates/parts/hello.php
You can read the official documentation on github.