Multiple WordPress themes within one site without a plugin

The theme I am describing here was not intended for resale or other applications beyond the organisation it is being created for, though it is possible to adapt it for that purpose. You can think about this theme as a custom built website that happen to use WordPress as a framework.

With such, lets say, one-off purpose, I found a very little use for e. g. archives – they are also problematic from the SEO point of view; templates – a lot of the code usually has to be copied and pasted over multiple files, which leads to problems with maintenance; template hierarchy – since we are using WordPress as a framework there is no need for such an extensive fallback mechanism.

The problem

A WordPress theme update usually requires some changes in the existing website content in order to adapt the Website to the new look and functionality. It is perfectly fine when we are dealing with a smaller websites and becomes more problematic with a bigger ones.

Often, we don’t really need to update the whole website, only the most important and recent pages or sections require a revamp. Sometimes we wish to have a different look and feel of certain pages within one domain, or even completely different functionality on each page.

WordPress provides some basic tools to do so such as: templates, custom headers, footers and sidebars. Though it is possible, up to some level, to build a completely independent layouts using those elements we might quickly run onto problems with maintainability of the code. Also there is a file called functions.php that is going to hold all of the new and old functions, this file is loaded every time the front or back-end page is being shown to the user, regardless or what is actually needed. That can sometimes significantly compromise our website’s performance.

Also we might want to work on entirely new theme concept and syncing all the files and database between localhost and the live, up to date version of the site, can be a pain.

The question

What if we could choose the theme for each page?

Of course the idea isn’t new and there are plugins available to do so. Unfortunately to utilise this plugin we have to trade a lot of the website’s performance, security and still won’t resolve many problems. It is rather quick and dirty solution for non-developers, that can lead to plugin overhaul and eventually render the website unresponsive.

The idea

  1. Each page or post has the ‘Theme Version’ assigned to it.
  2. Creating or modifying one of the theme versions doesn’t require updating any of the older / other theme versions.

Pros

  • Performance – very little overhead of data pulled from the server.
  • Maintainability – each theme sits in it’s own directory and can have directory structure optimal for the project (theme).
  • Security – no 3rd party plugins required.

Cons

  • Non-standard theme architecture.
  • WordPress native ‘template hierarchy’ and  include() function won’t work.
  • No support for child themes.

Only few ‘global’ files are required (index.php, functions.php, style.css) as the post meta containing the theme assignment is retrieved before the $_POST object, therefore further redirections are possible in the main functions.php – such as requiring selective functions for post, pages and admin and custom template components.

How it’s done

A first challenge was to retrieve the post meta before the init hook in order to load a version specific function.php etc. Turns out to be fairly simple.

First we need to retrieve the post ID somehow. As we doing it before the $_POST we cannot simply use get_the_ID() or similar function. Luckily there is a function called url_to_postid().


// add the action before the WordPress 'init' (refer to http://www.rarst.net/wordpress/wordpress-core-load/)

add_action('after_setup_theme', function (){

    // 'parse_url' neatly formats the uri
    $post_url = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH )

    // get the post ID before the $_POST
    $post_id = url_to_postid( $post_url );

    // get the post meta normal way
    $theme_version = get_post_meta( $post_id, 'theme_version', true);  

});

All the rest is really up to a developer’s preferences. In my work I like to keep things organised in folders such as this:


THEME ROOT
    functions.php
    index.php
    FAVICON
    THEME
        v1
        v2
        v3
            functions.php
            template_builder.php
            TEMPLATE_PARTS
                header.php
                local-nav.php
                local-footer.php
                breadcrumb-nav.php
            TEMPLATES
                generic.php
                profile-page.php
                large-hero.php

template_builder.php (or template_hierarchy.php) simply replaces the WordPress native template hierarchy and can be as simple as this:


if( is_author() ){
    include_once( 'templates/profile-page.php' ); // shows the author page even if author hasn't written any posts (not fully developed yet)
}

elseif ( have_posts() && !is_404() ) {

    the_post();

    $template = get_post_meta(( @get_the_ID() ),'template', true);
    if( empty( $template )) $template = 'generic' ;
    include_once( 'templates/'. $template . '.php' );

}
elseif( is_404() ){
    // ... 404 content
}

Join the Conversation

1 Comment

Leave a comment