Don’t “start the engine” in your Genesis child theme

Written by Gary Jones, originally published on GaryJones.io, and reposted here with permission.


There’s a line in the Genesis Sample theme, commented with “Start the engine”. All of the child themes by StudioPress have it. So do most child themes in the community.

However, it’s not needed.

More specifically, it doesn’t have to be needed.

It seems innocuous enough, so what’s the problem?

This article looks at the drawbacks of this start the engine approach while exploring some of the advantages an alternative setup function may provide.

Start The Engine

Let’s start at the beginning.

Child themes for the Genesis Framework by StudioPress, typically have a functions.php file that attempts to Start the engine:

<?php
//* Start the engine
include_once( get_template_directory() . '/lib/init.php' );

This line has been present since the very first version of Sample, and as such, it’s in every single StudioPress theme, and by a de facto standard, many child themes in the Genesis community.

Most people who have a passing understanding of PHP within WordPress themes should understand the code snippet above. Line one takes us into PHP mode, line two is a single-line comment, and line three is where the fun starts. It includes, once, a file called init.php within the lib/ sub-directory of the template directory (that’s the parent theme, aka Genesis, to you and me).

What Does init.php Do?

The init.php file within Genesis is the initialisation file. Here’s what it does (in Genesis 2.6 at least):

  • Sets up an autoloader for Genesis class files.
  • Calls a genesis_pre action hook.
  • Defines a genesis_i18n() function for loading Genesis language files, and hooks it into the genesis_init hook.
  • Defines a genesis_theme_support() function for adding theme support for Genesis and WordPress features, and hooks it into the genesis_init() hook.
  • Defines a genesis_post_type_support() function for enabling certain Genesis functionality for Posts and Pages, and hooks it into the genesis_init() hook.
  • Defines a genesis_post_type_support_post_meta() function for enabling Genesis functionality for post meta on public post types that are not Pages, and hooks it into the genesis_init() hook.
  • Defines a genesis_constants() function for defining PHP constants that Genesis uses within itself, and available to plugins and themes, and hooks it into the genesis_init() hook.
  • Defines a genesis_load_framework() function for loading in all the files, and hooks it into the genesis_init() hook.
  • Calls a genesis_init action hook, which therefore triggers calls to each function referenced above.
  • Calls a genesis_setup action hook.

Basically, that start the engine line makes every single bit of Genesis Framework load up straight away.

Advantages of the Start the Engine Approach

Let’s briefly discuss what some might say are the advantages of this method:

  • It’s one line. It’s easy to copy and paste, and even to remember, but you should know that lines of code are not an indicator of the quality of the code.
  • It loads all of Genesis up-front. The rest of the code in the functions.php file can reference Genesis functions, and the theme author doesn’t have to worry whether they are defined or not.

That’s probably about it.

Before going through the disadvantages, I want to introduce an alternative, so that we can make a comparison.

The Alternative: A Setup Function

The alternative is a setup function. Credit where credit is due, I call this the Bill Erickson Approach, as it was Genesis legend Bill Erickson who I first saw suggest this (though he may have got it elsewhere).

[Note from Bill: I got the idea from the default WordPress theme at the time, TwentyTwelve]

Here’s a trimmed example from Utility Pro by Carrie Dils. We’ll go through the reasoning in a moment:

<?php
add_action( 'genesis_setup', 'utility_pro_setup', 15 );
/**
* Theme setup.
*
* Attach all of the site-wide functions to the correct hooks and filters. All
* the functions themselves are defined below this setup function.
*
* @since 1.0.0
*/
function utility_pro_setup() {
define( 'CHILD_THEME_NAME', 'utility-pro' );
define( 'CHILD_THEME_URL', 'https://store.carriedils.com/utility-pro' );
define( 'CHILD_THEME_VERSION', '1.0.0' );
// Add HTML5 markup structure.
add_theme_support( 'html5', array( 'caption', 'comment-form', 'comment-list', 'gallery', 'search-form' ) );
// Add viewport meta tag for mobile browsers.
add_theme_support( 'genesis-responsive-viewport' );
// Add support for custom background.
add_theme_support( 'custom-background', array( 'wp-head-callback' => '__return_false' ) );
// Add support for accessibility features
add_theme_support( 'genesis-accessibility', array( 'skip-links', 'headings' ) );
// Add support for three footer widget areas.
add_theme_support( 'genesis-footer-widgets', 3 );
// Add support for additional color style options.
add_theme_support(
'genesis-style-selector',
array(
'utility-pro-purple' => __( 'Purple', 'utility-pro' ),
'utility-pro-green' => __( 'Green', 'utility-pro' ),
'utility-pro-red' => __( 'Red', 'utility-pro' ),
)
);
// Add support for structural wraps (all default Genesis wraps unless noted).
add_theme_support(
'genesis-structural-wraps',
array(
'footer',
'footer-widgets',
'footernav', // Custom.
'menu-footer', // Custom.
'header',
'home-gallery', // Custom.
'nav',
'site-inner',
'site-tagline',
)
);
// Add support for two navigation areas (theme doesn't use secondary navigation).
add_theme_support(
'genesis-menus',
array(
'primary' => __( 'Primary Navigation Menu', 'utility-pro' ),
'footer' => __( 'Footer Navigation Menu', 'utility-pro' ),
)
);
// Add custom image sizes.
add_image_size( 'feature-large', 960, 330, true );
// Unregister secondary sidebar.
unregister_sidebar( 'sidebar-alt' );
// Unregister layouts that use secondary sidebar.
genesis_unregister_layout( 'content-sidebar-sidebar' );
genesis_unregister_layout( 'sidebar-content-sidebar' );
genesis_unregister_layout( 'sidebar-sidebar-content' );
// Register the default widget areas.
utility_pro_register_widget_areas();
// Load files in admin.
if ( is_admin() ) {
// Add suggested plugins nag.
include get_stylesheet_directory() . '/includes/suggested-plugins.php';
// Add theme license (don't remove, unless you don't want theme support).
include get_stylesheet_directory() . '/includes/theme-license.php';
}
}
view raw functions.php hosted with ❤ by GitHub

Now that we’ve seen an example, let’s explain what it is.

What is a Setup Function?

setup function is one (or more) function(s) that includes much of the theme’s setup code, such as adding or removing theme support, adding or removing post type support, adding image sizes, defining menus for Genesis, registering widget areas, etc.

It’s not just for child themes, either. All of the default Twenty* themes have their own setup function (here’s TwentySeventeen’s), and Justin Tadlock has written about creating a theme setup function for themes in general.

For Genesis, we don’t call the setup function immediately, rather we hook it into the action hook that only fires after Genesis has finished loading, genesis_setup. Since Genesis itself also hooks into genesis_setup, we use a later priority of 15, to make sure the child theme adjustments come last.

While the example shows a single function, it would be equally possible to have multiple functions that organise the code into logical groups of function calls, and hook them all into the same hook and priority.

Advantages of the Setup Function Approach

There are a few advantages with this suggested approach that are worthy of explanation. These are:

  • Not including a file from another code base.
  • Honouring the default WordPress load order.
  • Fewer function calls in the global scope / everything is hooked in.
  • Allows functionality to be hooked in before Genesis loads.

Not including a file from another code base

Our code is inherently coupled to the file name of another code base (Genesis), and this is a bad idea. If it ever gets renamed (and with Genesis 3.x, that is a possibility), your code will throw a fatal error. You could do a file_exists() check, but if doesn’t exist, how will the rest of your code behave? Your code is still coupled to looking for that specific file name.

The solution brings us to our next point.

Honouring the Default WordPress Load Order

The whole point of child themes historically requiring that Genesis file, is so all of Genesis loads up first and we can use the Genesis functions.

But here’s a little secret.

The default behaviour for WordPress is to load the parent theme after the child theme. It will happen automatically. We should honour that behaviour.

The reason for letting this happen is simple. We stick to the expected behaviour for parent and child themes. We let WordPress load the Genesis functions.php file, which in turn loads the file we would have tried to load in our code.

If we don’t call any Genesis functions in the global scope (i.e. outside of a function hooked into a hook), then we don’t need Genesis to load first.

Fewer Function Calls in the Global Scope

PHP has scopes. Here, we’re considering two scopes: function scope and global scope.

Function scope is where we assign a variable, or make a function call, from inside a function.

Global scope is where the same thing might happen, but outside of a function.

<?php
function foobar() {
 // This is in the function scope.
}
// This is in the global scope.

Any function call in the global scope is called when the file is first loaded – that is, required or included by another file. In the case of a child theme functions.php file, that would be when WordPress is loading the (child) theme.

So why is this bad?

As plugin developers, we might want to alter how a theme runs, but if the theme makes a function call before we have a chance to intercept, we can’t make those changes.

However, if the critical function calls are all inside another (setup) function, which is hooked in to be called at a known time later, we can write plugin code to handle that; we can unhook that (setup) function, or have the plugin code run at an earlier or later priority as needed.

With a setup function, the theme itself could also handle specific edge cases that need a different setup i.e. for landing page templates.

It’s worth noting that this setup function approach isn’t for performance optimisation, but it certainly won’t noticeably impact performance either. The increase in executed byte-code is negligible within the request.

Allows Functionality to be Hooked in Before Genesis Loads

Delaying our code until after Genesis loads is all well, but can we use it to our advantage? Yes, we can.

As an example, let’s consider widget areas. By default, WordPress admin shows widget areas in the order they were registered, so all of our custom widget areas would typically appear below Header Right, Primary Sidebar and Secondary Sidebar.

If we create another setup function, but hook that into an earlier hook, or with a different priority, we can set things up before Genesis does. For example, if we display a Utility Bar widget area at the top of the site’s front-end, we could register it to appear in the Widgets admin page before Header Right. This may be more intuitive for users since the widget areas then follow the order they do on the front end.

Utility Bar widget area registered before the Header Right widget area from Genesis.

What Should You Put Into Your Setup Function?

So, should you put all of your global function calls into the setup function?

No, and here’s why.

Action and Filter Additions

Most add_action() and add_filter() can stay outside. There’s nothing special about these functions that has anything to do with Genesis, even if the callback they reference does. Keeping these by the callback function definitions makes code considerably easier to read, rather than having the function in one place and the context (hook) under which that function is called several hundred lines away or in a different file.

Could we move the add_action() call and the function definition into the setup function? This would create nested functions.

Nested Functions

Technically, PHP allows nested user-defined function. That is:

function foo() {
 // ...
 function bar() {
 // ...
 }
}

However, we should generally avoid nested functions, since you can’t call foo() more than once. Calling it a second time would make PHP attempt to define bar() again. Since a function by that name already exists from when foo() was first called, this would cause a fatal error.

In this case, it stops functions from being re-usable and should be avoided.

Action And Filter Removals

Unlike their add counterparts, the global remove_action() and remove_filter() calls may need to be in the setup function. One of the common gotchas is calling a remove_action() in the global scope, before Genesis has had a chance to add_action() in the first place. By including the remove_action() in the setup function, which in turn is not called until we know Genesis has finished setting up, the remove_action() intent will work.

WordPress Functions

WordPress functions like add_image_size()add_theme_support() and setting the global $content_width don’t need to be in the setup function, but equally, it makes sense to have them there, since they are part of setting up the theme behaviour.

Summary

Since the majority of customisations in Genesis Framework child themes require a hooked-in function, it makes perfect sense to add some of those global calls into one or more functions and hook them in as well.

Next time you’re editing a theme, consider not starting the engine by tying your code to Genesis internal file structure. Instead, take advantage of the WordPress event system and hook in your changes after WordPress automatically loads Genesis.

Genesis Theme Framework

Gary Jones

Gary Jones is a UK-based WordPress Engineer, code consultant, husband, and father of awesome twins. Driven by a passion for excellence, he develops elegant custom WordPress solutions for marketing departments to maximise their efficiency through his agency Gamajo, and provides services, including code audits, for other designers and developers.

Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments

Leave A Reply