Separating display and logic in your PHP templates


A quick tip when building your theme is to separate any logic to the display of your data. For example you might have this code (taken from the codex) in your single.php to loop through and show the categories for a particular post

<!--inside single.php -->
<div>
    <?php
        $categories = get_the_category();
        $separator = ' ';
        $output = '';
        if (!empty($categories)) {
            foreach ($categories as $category) {
                $output .= '<a href="' . esc_url(get_category_link($category->term_id)) . '" alt="' . esc_attr(sprintf(__('View all posts in %s', 'textdomain'), $category->name)) . '">' . esc_html($category->name) . '</a>' . $separator;
            }
            echo trim($output, $separator);
        }
    ?>
</div>

But by putting the code inside the template you’re mixing logic (looping through an array and manipulating the data inside) and the display of the data.

A cleaner way to do it is to separate out the logic into a function and then use that function in the single.php file instead. Where you put it will depend on personal preference and how you’ve set up your theme. Some options include:

  • A dedicated file for all of these which you require() into the functions.php
  • A file specific to the template file which you require() at the top of the template file
  • Directly creating the functions inside functions.php

To keep it simple, I’ll be putting mine into functions.php.

<!-- inside functions.php -->
<?php 
function display_categories_as_links() {
    $categories = get_the_category();
    $separator = ' ';
    $output = '';
    if (!empty($categories)) {
        foreach ($categories as $category) {
            $output .= '<a href="' . esc_url(get_category_link($category->term_id)) . '" alt="' . esc_attr(sprintf(__('View all posts in %s', 'textdomain'), $category->name)) . '">' . esc_html($category->name) . '</a>' . $separator;
        }
        echo trim($output, $separator);
    }
}

The same code as before but instead of echoing the output we are returning it. That’s because we will echo it inside the single.php file, which now looks like this

<!--inside single.php -->
<div><?php display_categories_as_links() ?></div>

We have a much cleaner template file now. This looks insignificant for just one particular instance but if you have a lot of data being output to the front end you can imagine how large the file can be. By separating each output into it’s own function, you end up with cleaner code, that’s easier to maintain and can be reused.

Need a web developer? Let’s chat