Mezzio 101: Adding Pages to a Mezzio Basic Application

In the previous article we used the Mezzio Skeleton Installer to build a very basic application. Let's explore what we can do with it right away.

The current components allow us to build a presentation site with static pages. It may not be much to speak of yet, but we can already create new pages.

Creating a new page

From the beginning, the Mezzio Skeleton Installer creates a home page that lists the components we chose during installation. Feel free to edit that page however you see fit. Don't worry about any dynamic twig elements for now.

What if you want a new page, like an 'About Us' page? Let's see how we can do this using this Mezzio CLI command.

composer mezzio mezzio:handler:create "App\Handler\AboutHandler"

Below are the new files created by the command:

  • src/App/src/Handler/AboutHandler.php
  • src/App/src/Handler/AboutHandlerFactory.php
  • config/autoload/mezzio-tooling-factories.global.php (unless it already exists)
  • src/App/templates/app/about.html.twig

The only thing left for us to do manually is set up the routing for our new page at http://localhost:8080/about.

Let's look at these changes in detail.

The new handler

A new file is created under src/App/src/Handler/AboutHandler.php. So far the only functionality it contains is to render the new template file.

<?php

declare(strict_types=1);

namespace App\Handler;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Laminas\Diactoros\Response\HtmlResponse;
use Mezzio\Template\TemplateRendererInterface;

class AboutHandler implements RequestHandlerInterface
{
    /**
     * @var TemplateRendererInterface
     */
    private $renderer;

    public function __construct(TemplateRendererInterface $renderer)
    {
        $this->renderer = $renderer;
    }

    public function handle(ServerRequestInterface $request) : ResponseInterface
    {
        // Do some work...
        // Render and return a response:
        return new HtmlResponse($this->renderer->render(
            'app::about',
            [] // parameters to pass to template
        ));
    }
}

The new factory

The new handler has a Factory created here src/App/src/Handler/AboutHandlerFactory.php. Its basically returns the AboutHandler class with a template renderer as a dependency.

<?php

declare(strict_types=1);

namespace App\Handler;

use Mezzio\Template\TemplateRendererInterface;
use Psr\Container\ContainerInterface;

class AboutHandlerFactory
{
    public function __invoke(ContainerInterface $container) : AboutHandler
    {
        return new AboutHandler($container->get(TemplateRendererInterface::class));
    }
}

The ConfigProvider file

The Factory must be registered in order to work, but this is also done automatically. The file config/autoload/mezzio-tooling-factories.global.php is created with this content:

<?php

/**
 * This file generated by Mezzio\Tooling\Factory\ConfigInjector.
 *
 * Modifications should be kept at a minimum, and restricted to adding or
 * removing factory definitions; other dependency types may be overwritten
 * when regenerating this file via mezzio-tooling commands.
 */
 
declare(strict_types=1);

return [
    'dependencies' => [
        'factories' => [
            App\Handler\AboutHandler::class => App\Handler\AboutHandlerFactory::class,
        ],
    ],
];

All future handlers created using the CLI will update this file with the required dependencies.

The new template

The handler returns a HtmlResponse with the template file app::about. If you check src/App/src/ConfigProvider.php, you can see what that string means under the getTemplates method:

  • app defines a folder in which the template file is kept, in this case __DIR__ . '/../templates/app' which resolves to src/App/templates/app.
  • about is the template filename without the extensions.

The template full name is about.html.twig and it initially has only this content:

Template for App\Handler\AboutHandler

We can replace that content to make use of the default template by overwriting about.html.twig with the below:

{% extends '@layout/default.html.twig' %}

{% block title %}About Us{% endblock %}

{% block content %}
    <div class="jumbotron">
        <h1>About Us</h1>
        <p>This is some great content!</p>
    </div>
{% endblock %}

The about template now extends the default template, meaning it uses its layout and populates its title and content blocks.

The routing

Finally, we need to add the new handler to the config/routes.php file by hand. On the bottom of the file we already have 2 entries created by the Mezzio Skeleton Installer. You can check the Handler names to tell what each of them is for.

For the new page, we need to append the line for the AboutHandler to that list, like we have done below. Below is what the return statement should look like:

return static function (Application $app, MiddlewareFactory $factory, ContainerInterface $container): void {
    $app->get('/', App\Handler\HomePageHandler::class, 'home');
    $app->get('/api/ping', App\Handler\PingHandler::class, 'api.ping');
    $app->get('/about', App\Handler\AboutHandler::class, 'about');
};

The result

You are done! Next make sure to have your web server started by running this command in your project folder php -S 0.0.0.0:8080 -t public. To visit your new page, type this url in the browser http://localhost:8080/about.

Additional Resources

Learn more about Command Line Tooling

Read the previous article in the series: Mezzio 101: Create an Application Using the Mezzio Skeleton Installer

Back to blog posts