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 name | Address | Action |
|---|---|---|
blog | /blog | index |
blog/view | /blog/5 | view |
blog/add | /blog/add | add |
blog/edit | /blog/edit/5 | edit |
blog/delete | /blog/delete/5 | delete |
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/5The 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.