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.