WordPress plugin structure, don't load unnecessary code

Published on Permalink

When developing WordPress plugins it is important to decide whether code needs to be loaded or not as early in the request lifecycle as possible. Why bother loading unnecessary code and hooking into actions and filters that will never run for the request being made? Having said that, it is also important to keep your code structured and not go overboard with this.

Conditional loading of code

What worked well for me so far is to split my code up into several files and load each of these files based on simple conditionals. While this might not do that much in terms of performance this will also help you in the long run by forcing a certain structure in your code.

Let's start with a no-brainer: admin section specific code versus public or frontend section specific code.

Do not load admin code in the public area

It makes no sense to load code that hooks into admin specific hooks for requests to the front page of a website. So let's split up our code into two files:
  • public.php, containing all public or frontend code, like shortcode callbacks and wp_enqueue_scripts hooks.
  • admin.php, containing all admin section code, like settings pages.

We can then load each of these files based on the outcome of the is_admin() function, which will return true if the URL begin requested is in the admin section.

define( 'MYPLUGIN_DIR', plugin_dir_path( __FILE__ ) );

// load code that ALWAYS needs to be loaded
// (registering post types, widgets, etc..)
require MYPLUGIN_DIR . 'includes/init.php'; 

if( ! is_admin() ) {
        // load code that only needs to be loaded for the public section
        // (stylesheets, shortcode callbacks, template functions, etc..)
        require MYPLUGIN_DIR . 'includes/public.php';
} else {
        // load code that is only needed in the admin section
        // (setting pages, admin menu, etc..)
        require MYPLUGIN_DIR . 'includes/admin.php';

AJAX requests

We can add one more conditional to the snippet above to differentiate between AJAX requests and regular (non-AJAX) requests. We can do this by checking for a constant named DOING_AJAX.

For AJAX requests, is_admin() will always return true, which makes it unnecessary to check for AJAX in requests for the public section. My complete initializing code usually looks something like this.

define( 'MYPLUGIN_DIR';, plugin_dir_path( __FILE__ ) );

// all requests
require MYPLUGIN_DIR . 'includes/init.php';

if ( !is_admin() ) {
        // public sectionrequests
        require MYPLUGIN_DIR . 'includes/public.php';
} else if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
                // AJAX requests
                require MYPLUGIN_DIR . 'includes/ajax.php';
} else {
        // admin section requests
        require MYPLUGIN_DIR . 'includes/admin.php';

Combining these 3 simple conditionals will keep the footprint of your plugin for each request as low as possible and forces you to follow a certain code structure, which you will benefit from in the long run.

Additions or suggestions? Please leave them in the comments. :-)