Master frontend templates in WordPress to build clean, MVC-compliant views for your plugin. Learn to pass data from controllers to the display layer.
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.
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:
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'; }
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>
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:
PHPpublic 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.
views/ folder in your plugin directory.single-kb-article.php and archive-kb-articles.php using the snippets above.ArticleController, create a method that fetches the current post and includes the single-article template.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).$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.esc_html(), esc_attr(), or wp_kses_post() for content.include, the template inherits the scope of the controller method. Be careful not to overwrite variables accidentally.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.
Learn to extend the WordPress REST API by registering custom endpoints. We'll show you how to securely serve your Knowledge Base data as structured JSON.
Creating Frontend Templates
Composer for Dependencies
Theme Integration Hooks
Managing Assets with Gulp/Webpack
Documentation Standards
Plugin Deployment Strategy
Advanced MVC: Dependency Injection
Handling Large Datasets
Error Handling and Logging