Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Child routes

Pages of one section have addresses that start the same way: /blog, /blog/5, /blog/add. To avoid repeating the common part in every route, routes are nested. A child route continues the parent's address and inherits its default values.

Parent and child

In the previous lesson the blog and post routes were written separately. Rewrite the router section in module/Blog/config/module.config.php like this:

// module/Blog/config/module.config.php
'router' => [
    'routes' => [
        'blog' => [
            'type' => Literal::class,
            'options' => [
                'route' => '/blog',
                'defaults' => [
                    'controller' => Controller\PostController::class,
                    'action' => 'index',
                ],
            ],
            'may_terminate' => true,
            'child_routes' => [
                'view' => [
                    'type' => Segment::class,
                    'options' => [
                        'route' => '/:id',
                        'constraints' => ['id' => '[0-9]+'],
                        'defaults' => ['action' => 'view'],
                    ],
                ],
            ],
        ],
    ],
],

The child's address is appended to the parent's: /blog plus /:id gives /blog/5. The child route names no controller — it is taken from the parent, only the action changes.

The may_terminate key

'may_terminate' => true means the parent's address — /blog — is a working page too. Without this key only the child routes match, and /blog itself returns a 404 error.

All blog routes

Add three more routes to child_routes — the next lessons need them:

'add' => [
    'type' => Literal::class,
    'options' => [
        'route' => '/add',
        'defaults' => ['action' => 'add'],
    ],
],
'edit' => [
    'type' => Segment::class,
    'options' => [
        'route' => '/edit/:id',
        'constraints' => ['id' => '[0-9]+'],
        'defaults' => ['action' => 'edit'],
    ],
],
'delete' => [
    'type' => Segment::class,
    'options' => [
        'route' => '/delete/:id',
        'constraints' => ['id' => '[0-9]+'],
        'defaults' => ['action' => 'delete'],
    ],
],

The result is this table:

Route nameAddressAction
blog/blogindex
blog/view/blog/5view
blog/add/blog/addadd
blog/edit/blog/edit/5edit
blog/delete/blog/delete/5delete

Names of child routes

A child route's name is written after the parent's name, separated by a slash. A link to a post is now built like this:

$url = $this->url('blog/view', ['id' => 5]); // /blog/5

The separate post route from the previous lesson is gone — blog/view replaced it.

Common mistake

If you refer to a child route without the parent's name — $this->url('view', ['id' => 5]) — Laminas throws an exception saying that a route with that name was not found. The name is always the full one: blog/view. A second, similar mistake is a forgotten may_terminate: the child pages open, but /blog answers 404.

Thanks for reading!

Donate to the site — we work hard for you.