Skip to main content
Version: Next

WordPress Controllers

Introduction

In the files (i.e. controllers) that WordPress uses when it matches a route (e.g. page.php, single.php), you can now use a class rather than writing procedural code.

// page-home.php

/*
* Template Name: Home Template
*/

namespace App;

use Timber\Timber;
use Rareloop\Lumberjack\Http\Responses\TimberResponse;

class PageHomeController
{
public function handle()
{
$context = Timber::context();

$context['post'] = Timber::get_post();

return new TimberResponse('home', $context);
}
}

The name of the controller is important:

  • It should be under the namespace App.
  • The class name must be an UpperCamelCase version of the filename with the word Controller on the end (without spaces, dashes and underscores). If the controller name is not correctly Lumberjack will not throw any errors - instead you will just get a blank page.

The handle method will automatically be called on your controller.

Changing the naming convention

If you wish to change how Lumberjack looks for controller class names, you can hook into the lumberjack_controller_name filter.

add_filter('lumberjack_controller_name', function ($controllerName) {
// e.g. Look for 'HomeController' instead of 'PageHomeController'
return str_replace('Page', '', $controllerName);
});

Or if you wish to change the namespace you can use the lumberjack_controller_namespace filter.

add_filter('lumberjack_controller_namespace', function ($controllerName) {
// e.g. Look for 'MyApp\PageHomeController' instead of 'App\PageHomeController'
return 'MyApp\\';
});

Controller for the 404 page

In WordPress, you have a 404.php file. PHP Classes cannot start with a number so following the usual naming convention will not work here.

Instead Lumberjack will look for a controller called Error404Controller

Password protected pages

info

Since: v6.1.0

WordPress supports password protection for pages across your site. This is also supported by Timber but requires you to implement it in each of your site's templates to take effect universally.

To make this simpler to implement, Lumberjack adds a middleware to handle this across all page templates. When a request is made for a page that requires a password it will intercept the call and attempt to render the single-password.twig file instead.

It is recommended that you implement the Twig file in line with what Timber suggests:

{% raw %}
{% extends "base.twig" %}

{% block content %}
{{ function('get_the_password_form') }}
{% endblock %}
{% endraw %}
info

Note: If a single-password.twig file is not found, the middleware will fall back gracefully to the default behaviour, which is to ignore the password functionality and render the page as normal.

Changing the Twig file used for password protected pages

If you would like to change the name of the Twig file that is used for password protection you can do so using the lumberjack/password_protect_template filter:

add_filter('lumberjack/password_protect_template', function() {
return 'my-password-template.twig';
});

Dependency Injection in WordPress Controllers

info

Available from v8.3.0, with full adoption in v9

In newer versions of Lumberjack, we've introduced dependency injection typehints for your WordPress controllers - for example:

class PageHomeController
{
- public function handle()
+ public function handle(TimberContext $context, Post $post)
{
- $context = Timber::context();
- $context['post'] = Timber::get_post();
+ $context->set('post', $post);

return new TimberResponse('home', $context);
}
}

This makes controllers much leaner, but critically, much more testable by de-coupling them from Timber.

Available Typehints

Any object bound in the Container can be typehinted, for example, Application $app or \Rareloop\Lumberjack\LoggerInterface.

For each Lumberjack type, there's full support for child classes. For example, injecting a custom post type will respect your Timber classmap.

TypehintDescriptionTimber Equivalent
\Rareloop\Lumberjack\TimberContextGet a Timber context singletonTimber::context()
\Rareloop\Lumberjack\PostQueryGet all the posts for the queryTimber::get_posts()
\Rareloop\Lumberjack\PostGet the current Post objectTimber::get_post()
\Your\Custom\PostTypeGet the current PostTypeTimber::get_post()
\Rareloop\Lumberjack\TermGet the current TermTimber::get_term()
\Your\Custom\CategoryTermGet the current CategoryTermTimber::get_term()
\Rareloop\Lumberjack\UserGet the current UserTimber::get_user()
\Your\Custom\AdminUserGet the current AdminUserTimber::get_user()
note

For each of Lumberjack's Proxy objects, the upstream Timber classes/interfaces are also supported. For example, typehinting \Timber\PostQuery will return an instance of that class.