Skip to main content

Routing

Routing is the process of determining what handler to use for an incoming request.

Defining Routes

In Neutomic, routing is done using one of the following methods:

Attribute Routing

Attribute routing uses attributes to define routes. It is the most common way to define routes in Neutomic.

<?php

declare(strict_types=1);

namespace App\Handler;

use Neu\Component\Http\Message\Method;
use Neu\Component\Http\Message\RequestInterface;
use Neu\Component\Http\Message\ResponseInterface;
use Neu\Component\Http\Message\Response;
use Neu\Component\Http\Router\Route\Route;
use Neu\Component\Http\Runtime\Context;
use Neu\Component\Http\Runtime\Handler\HandlerInterface;

#[Route(name: 'index', path: '/', methods: [Method::Get])]
final readonly class IndexHandler implements HandlerInterface
{
/**
* Handle the incoming request.
*/
public function handle(Context $context, RequestInterface $request): ResponseInterface
{
return Response\text('Hello, World!');
}
}

The #[Route] attribute is used to define a route. The name parameter is the name of the route, the path parameter is the path of the route, and the methods parameter is an array of HTTP methods that the route should match.

You can also define multiple routes in a single handler:

<?php

declare(strict_types=1);

namespace App\Handler;

use Neu\Component\Http\Message\Method;
use Neu\Component\Http\Message\RequestInterface;
use Neu\Component\Http\Message\ResponseInterface;
use Neu\Component\Http\Message\Response;
use Neu\Component\Http\Router\Route\Route;
use Neu\Component\Http\Runtime\Context;
use Neu\Component\Http\Runtime\Handler\HandlerInterface;

#[Route(name: 'index', path: '/', methods: [Method::Get])]
#[Route(name: 'about', path: '/about', methods: [Method::Get])]
final readonly class IndexHandler implements HandlerInterface
{
/**
* Handle the incoming request.
*/
public function handle(Context $context, RequestInterface $request): ResponseInterface
{
return Response\text('Hello, World!');
}
}

The IndexHandler class now has two routes: one for the root path (/) and one for the /about path.

Registry Routing

Registry routing uses a registry to define routes. It is less common than attribute routing but can be useful in some cases.

This method requires you to fetch the route registry from the container, create a route object, and register the route with the registry.

First, you need to define a dependency injection hook to add routes to the registry:

<?php

declare(strict_types=1);

namespace App\DependencyInjection\Hook;

use App\Handler\IndexHandler;
use Neu\Component\DependencyInjection\ContainerInterface;
use Neu\Component\DependencyInjection\HookInterface;
use Neu\Component\Http\Message\Method;
use Neu\Component\Http\Router\Route\Registry\RegistryInterface;
use Neu\Component\Http\Router\Route\Route;
use Neu\Component\Http\Runtime\Handler\HandlerInterface;

final readonly class RoutesHook implements HookInterface
{
/**
* @inheritDoc
*/
public function __invoke(ContainerInterface $container): void
{
$registry = $container->getTyped(
RegistryInterface::class,
RegistryInterface::class,
);

$route = new Route(name: 'index', path: '/index', methods: [Method::Get]);
$handler = $container->getTyped(IndexHandler::class, HandlerInterface::class);

$registry->register($route, $handler);
}
}

Then, you need to add the hook to the container:

<?php

declare(strict_types=1);

namespace App;

use Neu;
use Neu\Component\DependencyInjection\ContainerBuilder;
use Neu\Component\DependencyInjection\ContainerBuilderInterface;
use Neu\Component\DependencyInjection\Project;

use function Neu\Framework\entrypoint;

require_once __DIR__ . '/../vendor/autoload.php';

entrypoint(static function(Project $project): ContainerBuilderInterface {
$builder = ContainerBuilder::create($project);

// register your services, and extensions here
...

// Add the routes hook
$builder->addHook(new DependencyInjection\Hook\RoutesHook());

return $builder;
});

Now, when a request is made to the /index path, the IndexHandler class will be used to handle the request.

Generating URLs

You can generate URLs for routes using the GeneratorInterface service.

<?php

declare(strict_types=1);

namespace App\Handler;

use Neu\Component\Http\Message\Method;
use Neu\Component\Http\Message\RequestInterface;
use Neu\Component\Http\Message\ResponseInterface;
use Neu\Component\Http\Message\Response;
use Neu\Component\Http\Router\Generator\GeneratorInterface;
use Neu\Component\Http\Router\Route\Route;
use Neu\Component\Http\Runtime\Context;
use Neu\Component\Http\Runtime\Handler\HandlerInterface;

#[Route(name: 'home', path: '/home', methods: [Method::Get])]
final readonly class HomeHandler implements HandlerInterface
{
public function __construct(
private GeneratorInterface $generator,
) {}

public function handle(Context $context, RequestInterface $request): ResponseInterface
{
$url = $this->generator->generate('index');

return Response\redirect(location: $url);
}
}

In the example above, the HomeHandler class generates a URL for the index route and redirects the user to that URL.