Skip to content
On this page

Template Controllers

In the files that WordPress uses when it matches a route (e.g. page.php, single.php), or within custom theme templates, you can use a controller class rather than writing procedural code.

We call these Template Controllers to distinguish them from ones that haven't been hoisted from WordPress templates. In most respects, they follow the same pattern as standard controllers

php
// single.php

declare(strict_types=1);

namespace NameSpace\AppName;

use YourNameSpace\AppName\Core\View;
use Forme\Framework\Controllers\AbstractController;
use Psr\Http\Message\ServerRequestInterface;

final class SingleController extends AbstractController
{
    public function __construct(private View $view)
    {
    }

    public function __invoke($request)
    {
        $context = $request->input('fields');
        return $this->view->render('single', $context);
    }
}

The name of the controller is important

  • It should be under your app namespace (even though this doesn't follow PSR-4)
  • The class name must be a PascalCase version of the filename with the word Controller on the end (without spaces, dashes and underscores). If the controller name is not correct Forme will not throw any errors - instead you will just get a blank page.

Exceptions

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 Forme will look for a controller called Error404Controller.

Template controller classes won't work for the WordPress header.php and footer.php files. In the Forme theme boilerplate these have been done away with entirely in any case, and reimplemented as view partials, so you shouldn't need to use them.

Magic to be aware of

When someone views a page that has a corresponding template controller, the __invoke method will automatically be called on that controller, and will have $request passed into it with postId, fields and options pre-filled as part of its body parameters. That fields value helpfully contains an array with all the ACF fields for the postId, the options value contains an array with all the global options page values.

WARNING

The fields and options keys will all be converted to camelCase from the ACF default of snake_case. This is mainly so you can access my_awesome_field as $myAwesomeField in the view.

Custom Template Controllers

As a convention, we put custom template controllers in the /template-controllers directory.

You can add template names to template controllers and they will be picked up for selection in the WordPress admin:

php
// template-controllers/FooBarController.php;
<?php
declare(strict_types=1);

namespace NameSpace\AppName\Controllers;

use YourNameSpace\AppName\Core\View;
use Forme\Framework\Controllers\AbstractController;

/*
 * Template Name: Foo Bar
 */
final class FooBarController extends AbstractController

Middleware

Check out this section to find out how to add PSR 15 middleware to Template Controllers.

Code Generation

You can use the code generator.

bash
forme make template-controller FooBar

This will create a new custom template controller called FooBarController in the template-controllers folder.

Made by Moussa Clarke @ Sanders Web Works with ❤️