Back to Blog
Lesson 23 of the WordPress Plugin Development: Foundations (PHP & MVC) course
WordPressJune 25, 20263 min read

Creating Frontend Templates: Professional MVC Views in WordPress

Master frontend templates in WordPress to build clean, MVC-compliant views for your plugin. Learn to pass data from controllers to the display layer.

WordPressPHPMVCTemplatesViewsFrontendDevelopmentplugin-development

Previously in this course, we explored Mastering the Plugin Template Hierarchy for WordPress, which taught us how to locate files within themes. Now, we're moving from theory to implementation: we will build the actual view layer for our Knowledge Base plugin, ensuring our display logic remains strictly separated from our business logic.

In a true MVC architecture, the controller handles the request, fetches the data via the model, and then "hands off" that data to a view (a template file) to be rendered. This keeps your code maintainable and allows theme developers to override your output easily.

The MVC View Philosophy

In WordPress, "views" are simply PHP files that contain HTML mixed with minimal PHP logic. We never perform database queries inside our templates. Instead, we prepare all necessary data in our ArticleController and pass it to the view.

To maintain consistency, we will create a views/ directory in our plugin structure. This directory will house two types of templates:

  1. Single Templates: For displaying one specific Knowledge Base article.
  2. Archive Templates: For displaying a list of all articles.

Worked Example: Rendering a Single Article

First, let's create a template file at views/single-kb-article.php. This file will receive an $article object from our controller.

PHP
<?php
#6A9955">// views/single-kb-article.php
#6A9955">// We expect $article to be passed as an object
?>
<article class="kb-article">
    <h1><?php echo esc_html($article->post_title); ?></h1>
    <div class="kb-content">
        <?php echo apply_filters('the_content', $article->post_content); ?>
    </div>
</article>

Now, we need our controller to render this. In your ArticleController, you'll create a method that loads this view while ensuring the data is available in the local scope.

PHP
#6A9955">// Inside ArticleController.php
public function render_single_view($post_id) {
    $article = get_post($post_id); #6A9955">// In a real app, use your Model layer
    
    #6A9955">// Pass $article to the view
    include plugin_dir_path(__FILE__) . '../views/single-kb-article.php';
}

Creating the Archive Template

For our archive, we need to iterate over a collection of articles. Create views/archive-kb-articles.php:

PHP
<?php
#6A9955">// views/archive-kb-articles.php
#6A9955">// Expects $articles to be an array of WP_Post objects
?>
<div class="kb-archive">
    <?php if (!empty($articles)) : ?>
        <ul>
            <?php foreach ($articles as $article) : ?>
                <li>
                    <a href="<?php echo get_permalink($article->ID); ?>">
                        <?php echo esc_html($article->post_title); ?>
                    </a>
                </li>
            <?php endforeach; ?>
        </ul>
    <?php else : ?>
        <p>No articles found.</p>
    <?php endif; ?>
</div>

Passing Data from Controller to View

The key to clean MVC is the "data injection" pattern. Your controller should be the only place where data is prepared.

When your controller calls the template, it should look like this:

PHP
public function render_archive() {
    #6A9955">// 1. Fetch data from Model
    $articles = $this->model->get_all_articles();
    
    #6A9955">// 2. Buffer the output to prevent premature rendering
    ob_start();
    include plugin_dir_path(__FILE__) . '../views/archive-kb-articles.php';
    return ob_get_clean();
}

By using ob_start() and ob_get_clean(), we capture the HTML generated by the template into a variable. This is crucial for shortcodes or filters where you need to return a string rather than echoing it immediately.

Hands-on Exercise

  1. Create a views/ folder in your plugin directory.
  2. Create single-kb-article.php and archive-kb-articles.php using the snippets above.
  3. In your ArticleController, create a method that fetches the current post and includes the single-article template.
  4. Use the template_include filter to force WordPress to load your plugin's template when a user views a single Knowledge Base article. (Hint: Use the logic covered in our previous lesson on template hierarchy).

Common Pitfalls

  • Direct Database Queries in Views: Avoid calling $wpdb or get_posts() inside your template files. If you find yourself doing this, move that logic to your Model Layer and pass the results to the view.
  • Security Neglect: Never echo variables directly without escaping. Always use esc_html(), esc_attr(), or wp_kses_post() for content.
  • Variable Scope: When using include, the template inherits the scope of the controller method. Be careful not to overwrite variables accidentally.

Recap

We've successfully decoupled our display layer from our logic. By creating specific view files and utilizing output buffering in our controllers, we've built a professional-grade template system. This structure ensures that your code remains clean, secure, and easy to extend as we continue building our Knowledge Base plugin.

Up next: We will take these views and make them accessible anywhere on your site by Building Shortcodes.

Similar Posts