Using Fractal Templates Part 2: Template Inheritance

My previous post focused on how classes can be used with WordPress themes and gave you a taste for how a Fractal index page looks. This post will cover how child files inherit from index.php’s Fractal class. We’ll use single.php as an example to show how it interacts with index.php.

To explain in detail how this relationship works, we’ll first have to define the parent file: index.php.

if ( ! defined( 'FRACTAL_LEAF' ) )
    define( 'FRACTAL_LEAF', __FILE__ );

class Fractal {
  function __construct() {?>
    <!DOCTYPE html>
    <html>
      <head>
        <?php $this->html_head(); ?>
      </head>

      <body <?php $this->body_classes(); ?>>
        <?php $this->body(); ?>
      </body>
    </html>
  <?php
  }

  function head() {
    // The html element 
    // Most of the contents of a typical WordPress theme’s header.php file go here.
    wp_head();
  }

  function body() {
    // The HTML element
    $this->header();
    $this->main_content();
    $this->sidebar();
    $this->footer();
  }

  function body_class() { body_class(); }

  function header() {
    // Header navigation would go here
  }

  function main_content() {
    // Main Content ‘Index’ php/html
  }

  function sidebar() {
    // Sidebar ‘Index’ php/html ?>

    <aside class="sidebar"><!--?php <br ?--> do_action( 'before_sidebar' );
    dynamic_sidebar( 'default_sidebar' );
    ?></aside><!-- end .sidebar -->
  <?php
  }

  function footer() {
    // Contents of footer.php go in here
    // don’t forget to include wp_footer()
    wp_footer();
  }
}

if ( FRACTAL_LEAF === __FILE__ )
  new Fractal();

I’ve changed a few things from the index.php from the last post. Most importantly, I’ve added definitions for the methods main_content() and sidebar(). Now this file seems to be getting a bit large. So how big will single.php be?

Well, that depends on what the differences are between single.php and index.php. No matter what, the following code needs to be added to single.php for Fractal to work.

// If no file is set as the FRACTAL_LEAF,
// then set it to this file
if ( ! defined( 'FRACTAL_LEAF' ) )
  define( 'FRACTAL_LEAF', __FILE__ );

// import parent template
locate_template( "index.php", true );

class FractalSingle extends Fractal {
  // Code unique to single.php goes here
}

if ( FRACTAL_LEAF === __FILE__ )
  new FractalSingle();

There are 3 key things that are added in single.php, as well as any other child file, so it can inherit from index.php:

  1. locate_template() makes the parent class Fractal available to inherit from, by loading the file where it is defined
  2. class FractalSingle extends Fractal begins to define our new class, and extends it from Fractal so it will inherit all the Fractal’s methods
  3. The last line needs to use the class defined in this file, in this case FractalSingle (The convention we’ve been using for child class names is ‘Fractal’ + camel-cased file name)

Because FractalSingle inherits from Fractal, every method of Fractal is also a part of FractalSingle. In its current state, single.php might as well not exist. It is creating a class that has no methods itself, simply inheriting everything from index.php’s Fractal class. Now, we have to decide what makes single.php different from index.php. Then we will add these differences to FractalSingle to make it unique.

This is an example of a FractalSingle class that appends something to the end of the main content:

class FractalSingle extends Fractal {
  function main_content(){
    parent::main_content();
    $this->content_appendage();
  }

  function content_appendage() {
    // What you want to append to the main content,
    // like a mailing list opt-in form
  }
}

Methods defined by FractalSingle that already existed in Fractal will be re-defined for the FractalSingle class, replacing the inherited versions. This is called overriding and is an integral part of Object Oriented Programming (OOP). In the example above, we have overridden Fractal’s version of the method main_content(). Now, whenever WordPress displays a single blog post, the code in method content_appendage() will run, in this case, displaying a mailing list opt-in form. This will only happen on single blog posts. Any other template will run the Fractal class’ version of main_content().

For those unfamiliar with the keyword parent in parent::main_content(), it is used to call parent’s version of the method. In this case, it calls the main_content() defined in index.php. This trick is very useful for having a child method that simply add something to the parent’s method.

This example gives single.php a different sidebar:

class FractalSingle extends Fractal {
  function sidebar(){ ?>
    do_action( 'before_sidebar' );
    <aside class="sidebar"><?php dynamic_sidebar( 'single_sidebar' ); ?></aside>
  <?php 
  }
}

Here is one advantage of Fractal’s object-oriented approach to theming: The child file single.php is only made up of the differences between index.php and single.php, which makes child files much shorter than their non-Fractal equivalents. In turn, single.php can be a parent to another file, perhaps single-post.php. Fractal is not limited to a set depth of its inheritances.

Here is one final example where the content should change site-wide. To do this, just change the code in index.php, because every page inherits from index.php.

class Fractal {
  // everything except this method is the same as the version above
  function main_content() {
    // Main Content ‘Index’ php/html

  }
}

In the next post we’ll go into how Fractal and the template hierarchy work together.

Leave a Reply