Skip to content

Instantly share code, notes, and snippets.

@kevindees
Last active March 19, 2020 13:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevindees/afc8cd02b33adfbf9ab546344be8d941 to your computer and use it in GitHub Desktop.
Save kevindees/afc8cd02b33adfbf9ab546344be8d941 to your computer and use it in GitHub Desktop.

About

If you ever wanted MVC for your WordPress theme's template files without a framework or reduced WordPress performance. If you ever wanted to register template files like single.php, index.php, page.php, and so forth in PHP instead of creating them as files in your theme. All you need is a blank index.php file and a few lines of code.

Getting Started

Add these classes to your WordPress site (in your functions.php file is just fine). Then add the following to your theme after creating a blank index.php file (must be blank) in your theme:

$override = new TemplateOverride(__DIR__ . '/index.php');
$override->index('index.php', function() {
    echo 'My index';
});
$override->page('page.php', function() {
    echo 'My page!';
});
$override->initHooks();

Now, visit your website's home page. You should see My page!. All without the page.php template file created for your theme!

Using

You can register your templates dynamically using the methods on the TemplateOverride class. The method you should use will logically correspond to the standard WordPress template hierarchy file patten.

Important

When using this system your theme's template files will get used unless you have registered a template using the new system of your theme's template type.

<?php
class TemplateOverrideContainer {
public $active = [];
public $slugs = [];
public $force;
public $templates = [];
public $found;
public $core_template;
public $options = [ 'index' => [], '404' => [], 'archive' => [], 'author' => [], 'category' => [], 'tag' => [], 'taxonomy' => [], 'date' => [],
'embed' => [], 'home' => [], 'frontpage' => [], 'privacypolicy' => [], 'page' => [], 'paged' => [], 'search' => [], 'single' => [], 'singular' => [], 'attachment'];
public function __construct($core_template, $force = false)
{
$this->core_template = $core_template;
$this->force = $force;
}
public function runTemplate($template)
{
if($this->slugs[$this->found] ?? null) {
call_user_func($this->slugs[$this->found]);
}
return $template;
}
public function blockTemplates($templates)
{
$this->templates = $templates;
return $this->force ? [] : $templates;
}
public function process($current, $type)
{
$templates = $this->options[$type];
foreach ($this->templates as $temp) {
if(in_array($temp, $templates)) {
$this->found = $temp;
return $this->core_template;
}
}
return $current;
}
}
class TemplateOverride {
protected $container;
public function __construct($core_template, $force = false)
{
$this->container = new TemplateOverrideContainer($core_template, $force);
}
public function index($slug, $caller)
{
return $this->template('index', $slug, $caller);
}
public function error($slug, $caller)
{
return $this->template('404', $slug, $caller);
}
public function archive($slug, $caller)
{
return $this->template('archive', $slug, $caller);
}
public function author($slug, $caller)
{
return $this->template('author', $slug, $caller);
}
public function category($slug, $caller)
{
return $this->template('category', $slug, $caller);
}
public function tag($slug, $caller)
{
return $this->template('tag', $slug, $caller);
}
public function taxonomy($slug, $caller)
{
return $this->template('taxonomy', $slug, $caller);
}
public function date($slug, $caller)
{
return $this->template('date', $slug, $caller);
}
public function paged($slug, $caller)
{
return $this->template('paged', $slug, $caller);
}
public function single($slug, $caller)
{
return $this->template('single', $slug, $caller);
}
public function singular($slug, $caller)
{
return $this->template('singular', $slug, $caller);
}
public function attachment($slug, $caller)
{
return $this->template('attachment', $slug, $caller);
}
public function page($slug, $caller)
{
return $this->template('page', $slug, $caller);
}
public function privacy($slug, $caller)
{
return $this->template('privacypolicy', $slug, $caller);
}
public function front($slug, $caller)
{
return $this->template('frontpage', $slug, $caller);
}
public function home($slug, $caller)
{
return $this->template('home', $slug, $caller);
}
public function embed($slug, $caller)
{
return $this->template('embed', $slug, $caller);
}
public function search($slug, $caller)
{
return $this->template('search', $slug, $caller);
}
/**
* @param string $type
* @param string $slug
* @param string|callable $caller
*
* @return $this
*/
public function template($type, $slug, $caller)
{
$this->container->active[$type] = true;
$this->container->options[$type][] = $slug;
$this->container->slugs[$slug] = $caller;
return $this;
}
/**
* Init hooks after templates have been registered
*/
public function initHooks()
{
foreach ($this->container->active as $type => $bool) {
add_filter( "{$type}_template_hierarchy", [$this->container, 'blockTemplates'] );
add_filter( "{$type}_template", [$this->container, 'process'], 10, 2);
add_filter( "template_include", [$this->container, 'runTemplate'], 100);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment