Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Routing

A route connects a page address to the code that builds the response. Laminas has no single file with all addresses: each module describes its routes in the router section of module/<Module>/config/module.config.php.

The first route

Open module/Blog/config/module.config.php and replace the empty array:

// module/Blog/config/module.config.php
namespace Blog;
 
use Laminas\Router\Http\Literal;
 
return [
    'router' => [
        'routes' => [
            'blog' => [
                'type' => Literal::class,
                'options' => [
                    'route' => '/blog',
                    'defaults' => [
                        'controller' => Controller\PostController::class,
                        'action' => 'index',
                    ],
                ],
            ],
        ],
    ],
];

What each key means:

KeyMeaning
blogThe route name. Links are built from it later
typeThe route type. Literal is an exact address match
routeThe address itself
defaults.controllerThe controller class that answers the request
defaults.actionThe action — the controller method indexAction()

Open http://localhost:8080/blog. You get an error page explaining that the controller was not found. That is expected: the route already matched, and the PostController class is created in the controllers lesson. Before the route was added, the same address answered that the page was not found.

A route with a parameter

The Segment type lets you put a variable part — a parameter — into the address. A parameter starts with a colon. Add a second route next to the first one, inside routes:

// at the top of the file: use Laminas\Router\Http\Segment;
'post' => [
    'type' => Segment::class,
    'options' => [
        'route' => '/blog/:id',
        'constraints' => [
            'id' => '[0-9]+',
        ],
        'defaults' => [
            'controller' => Controller\PostController::class,
            'action' => 'view',
        ],
    ],
],

The address /blog/5 goes to the view action, and the number 5 becomes the id parameter. The constraints section sets a regular expression for the parameter: here id is digits only, so /blog/anna does not match this route.

An optional part

The part of the address in square brackets may be left out. The default value comes from defaults:

'archive' => [
    'type' => Segment::class,
    'options' => [
        'route' => '/archive[/:year]',
        'constraints' => ['year' => '[0-9]{4}'],
        'defaults' => [
            'controller' => Controller\PostController::class,
            'action' => 'archive',
            'year' => 2025,
        ],
    ],
],

The route answers both /archive and /archive/2024. In the first case year equals 2025.

Route types

TypePurpose
LiteralAn exact address without parameters — the fastest
SegmentAn address with parameters: /:id, /:year/:month
RegexAn address matched by a regular expression
MethodA restriction by HTTP method

Linking to a route

Addresses are not typed by hand in the code — they are built from the route name. In a view script the url() helper does it: $this->url('post', ['id' => 5]) returns the string /blog/5. If the address in the configuration changes, every link changes with it.

Common mistake

A parameter without a constraint accepts any text. The route /blog/:id without constraints also matches /blog/add, and the action receives an id equal to add. Always set a constraint for numeric parameters: 'id' => '[0-9]+'.

Thanks for reading!

Donate to the site — we work hard for you.