Saturday, February 25, 2012

Refactoring your wordpress theme with Skellie

Skellie allows for maintainable, readable, reusable code within wordpress themes without breaking wordpress or plugins. It gives you a simple but powerful toolbox with structured partials, layouts and templates.


If you want to see what other problems Skellie solves view my presentation about it

  • Download Skellie
  • Copy the directories: layouts, library and partials into your theme's main dir.
  • Add the following in your functions.php :

Refactoring a single template
Let's refactor the home page.
Remove get_header() and get_footer() from your template and choose a layout at the top within comments like this:
 * @layout myOwnLayout
Enabling the cherry picking requirement during installation allows Skellie to take over rendering but only for templates that explicitely ask for a layout. All your remaining templates will continue using wordpress. 

Refactoring the template into a layout and basic partials 
Step 1 - Merge into a working layout
By convention wordpress themes split wrapping code into header.php and footer.php and then call get_header(), get_footer() within the template.
Create layouts/myOwnLayout.php and copy the contents of your header.php.
<?php echo $this->content(); ?>
then finish up with the contents of footer.php.
Your homepage template is now powered by Skellie, is pretty much an unreadable mess, but should work as before and you can begin cleaning it up.

Step 2 - Split into default partials
Now you can start cleaning up the mess.
  1. Move your starting html-tag and <head>.*</head> into partials/header.php and replace the code in the layout with
    <?php echo $this->partial('header'); ?>
  2. Leave the starting body-tag intact or replace it with
    <body <?php body_class('layout-'.$this->layout); ?>>
    That will give the body-tag classes of both the layout and the template, so you can minimize the need of creating more layouts. 
  3. Move your common html code that lies right before the ending body-tag [including wp_foot()] into partials/footer.php. Mine contains just a wp_foot call and a chrome-frame snippet.
  4. Replace that code with
    <?php echo $this->partial('footer'); ?>
Up until this point you haven't won anything special. It's basically the same as wordpress does but renaming "template" to "layout".
Let's bring it up a notch.

Step 3 - Split your layout in organized partials
  1. Replace all get_template_part($slug, $name) calls with:
    <?php echo $this->partial($slug, $name); ?>
    Copy the contents of {$slug}-{$name}.php into partials/$slug/$name.php
    The idea is to eventually delete all partials from the main theme dir when templates no longer need them.
  2. Create a directory partials/navigation
  3. Move every navigation menu code into it's own file in partials/navigation/{$name}.php and replace the code in the layout with:
    <?php echo $this->partial('navigation', $name); ?>
  4. Move remaining wordpress (e.g. a search form or sidebars) or plugin code (e.g. breadcrumbs) to its own file and replace it with partial() calls.
    If you do not use subtypes for a certain partial you can store the code in partials/{$slug}.php and there is no need to create a directory for it.
Step 4 - Cleanup your template code
Now the layout should be clean but your template is still full of code.
You can use partials however you want to lighten it up.
My conventions are : 
  • partials/list/$type.php for aggregating posts of a type (cat, post_type etc)
  • partials/preview/$type.php for showing an excerpt of a single post
  • partials/content/$type.php for showing the full content of a single post
  • partials/pagination/$type.php for things like next/previous article, wp_paginate or link to a list of articles
But first the fun part.
Chance is you would end up creating partials for a certain slug that do not differ that much between types.
Use the 3rd parameter of partial() to pass arguments to your partial:

Whatever parameters are passed through the associative array are accessible through the partial as public variables of $this. (If a param is not set it always returns null)
For example within partials/list/category.php you could do:
That's it.
Feel free to fork it or submit issues that arise on github.

No comments:

Post a Comment