Use generic views with data arrays for a flexible, context-independent UI system

When you start digging into WordPress partials, things really open up on the theme side. Being able to reuse templates is a nice feature and can help keep your code nice and tidy but if your templates are using WordPress’ template tags, you can easily find yourself in situations where you need the markup from a partial but not the data.

To work around this, I use generic views that depend only on an array of data points. This allows me to reuse the same view in multiple places on a site without having to worry if I’m inside a post loop or rendering a specific template, etc. This really opens up flexibility in the UI and also makes it possible to move UI components between projects quite easily.

The basic use example

Once set up, rendering your views is as simple as the following:

<?php
View::render( 'post-single', [
'post_title' => get_the_title(),
'content' => get_the_content(),
'author' => get_the_author(),
] );

Keeping the templates clean and ‘dumb’

The templates themselves all initialise their expected variables at the top of the file and the markup below. You’ll see there are no WordPress template tags in here which removes the context-dependency. ‘Dumb’ templates are nice and versatile.

<?php
$data = isset( $data ) ? $data : new stdClass();
$post_title = isset( $data->post_title ) ? $data->post_title : "";
$author = isset( $data->author ) ? $data->author : "";
$content = isset( $data->content ) ? $data->content : "";
?>
<div class="PostSingle">
<?php if ( $post_title ): ?>
<h1 class="PostSingle__title"><?= $post_title ?></h1>
<?php endif; ?>
<?php if ( $author ): ?>
<div class="PostSingle__author"><?= $author ?></div>
<?php endif; ?>
<?php if ( $content ): ?>
<div class="PostSingle__content"><?= $content ?></div>
<?php endif; ?>
</div>
view raw post-single.php hosted with ❤ by GitHub

Setting up the View class so it knows where your templates live

The View class (which I’ve provided further down) is simple to set up and it only needs to know where to look for templates.

<?php
include 'inc/View.php';
View::$view_dir = get_stylesheet_directory() . '/templates';
view raw functions.php hosted with ❤ by GitHub

An example of how to use the views in a WordPress template

Just so you understand the use-case, here is an example of the View class being used within a WordPress template to render a view.

<?php
get_header();
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
View::render( 'post-single', [
'post_title' => get_the_title(),
'content' => get_the_content(),
'author' => get_the_author(),
] );
}
} else {
?>
<p>No post found.</p>
<?php
}
get_footer();
view raw index.php hosted with ❤ by GitHub

Finally, the View class itself

The View class is a static class the is super simple to configure and just as easy to use as you’ve seen from the previous Gists. You are free to take, use, and modify this class however you need to.

<?php
class View {
public static $view_dir = '';
/**
* Render View Template With Data
*
* Locates a view template and includes it within the same scope as a data object/array. This makes it possible to
* access raw data in the template.
*
* Note: Any data passed into this function will be casted as an array and then as an object. The final data available
* within a template is in the form of an object with the variable name $data.
*
* e.g.
*
* array('name' => 'Bob', 'age' => 42)
*
* Will be converted to an object to be used as;
*
* $data->name
* $data->age
*
* @param string|null $name A named variation for the template. This is in the form {$name}.php. Can include directories, where necessary.
* @param object|array $data An associative array or object to use inside the template.
* @param string $suffix The file suffix.
*
* @return string
*/
public static function prepare( $name, $data = [], $suffix = '.php' ) {
$markup = '';
$path = self::get_full_path( $name . $suffix );
if ( $t = self::view_template_exists( $path ) ) {
$data = self::prepare_data( $data );
ob_start();
include $path;
$markup = ob_get_clean();
}
return $markup;
}
/**
* Use this to echo out templates
*
* @param $name
* @param array $data
* @param string $suffix
*/
public static function render( $name, $data = [], $suffix = '.php' ) {
echo self::prepare( $name, $data, $suffix );
}
/**
* Casts data to an object for use int the template
*
* @param $data
*
* @return object
*/
private static function prepare_data( $data ) {
// if data is not already an object, cast as object
if ( ! is_object( $data ) ) {
$data = (object) (array) $data;
}
return $data;
}
/**
* Making sure the template exists
*
* @param $name
*
* @return bool
*/
private static function view_template_exists( $name ) {
return file_exists( $name );
}
/**
* Pieces together the full path to the file
*
* @param $name
*
* @return string
*/
private static function get_full_path( $name ) {
return trailingslashit( self::$view_dir ) . ltrim( $name, '/' );
}
}
view raw class-view.php hosted with ❤ by GitHub

Got a project? Let's talk.

From website design & SEO through to custom WordPress plugin development. I transform ideas into dynamic, engaging, and high-performing solutions.
Subscribe to get the latest insights & updates in the world of web and how it impacts your business and website.
© 2024 Phil Kurth  |  All rights reserved.