Laravel-routes declareren met klassen in plaats van bestanden

Laravel-routes declareren met klassen in plaats van bestanden

In dit artikel laat ik zien hoe je je routes netjes declareert via een klasse Route Registrers waarin je ze registreert. Het is een schone en eenvoudige manier om routes te declareren.

De aanpassingen aan je Laravel-applicatie zijn tamelijk eenvoudig. We wijzigen de route service provider op een paar punten en verwijderen de routebestanden voor web en API. Als eerste maken we een nieuwe trait/concern die we aan onze app/Providers/RouteServiceProvider kunnen toevoegen, genaamd MapRouteRegistrers. Zet de volgende code in die nieuwe trait/concern.

php
namespace App\Routing\Concerns;

use App\Routing\Contracts\RouteRegistrer;
use Illuminate\Contracts\Routing\Registrer;
use RuntimeException;

trait MapRouteRegistrers
{
	protected function mapRoutes(Registrer $router, array $registrers): void
	{
		foreach ($registrers as $registrer) {
			if (! class_exists($registrer) || ! is_subclass_of($registrer, RouteRegistrer::class)) {
				throw new RuntimeException(sprintf(
					'Cannot map routes \'%s\', it is not a valid routes class',
					$registrer
				));
			}

(new $registrer)->map($router);
		}
	}
}

Zoals je ziet moeten we ook een interface/contract maken, en ervoor zorgen dat al onze Registrers die implementeren.

Maak hem aan onder App/Routing/Contracts/RouteRegistrer en zet er de volgende code in.

php
namespace App\Routing\Contracts;

use Illuminate\Contracts\Routing\Registrer;

interface RouteRegistrer
{
	public function map(Registrer $registrer): void;
}

Nu de trait en de interface klaarstaan, kunnen we kijken naar de wijzigingen die de standaard route service provider nodig heeft.

php
namespace App\Providers;

use App\Routing\Concerns\MapsRouteRegistrers;
use Illuminate\Contracts\Routing\Registrer;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider
{
	use MapsRouteRegistrers;

protected array $registrers = [];

public function boot(): void
	{
		$this->routes(function (Registrer $router) {
			$this->mapRoutes($router, $this->registrers);
		});
	}
}

In de code hierboven zie je dat we een nieuwe property aan onze route service provider hebben toegevoegd. In die property worden de route registrers van de applicatie geregistreerd, en de bootmethode laadt ze.

Nu de applicatie klaar is om route registrers te gebruiken in plaats van routebestanden, maken we er een standaardversie voor. Deze aanpak werkt uitstekend in een modulair systeem of een domain-driven opzet – elk domein of elke module registreert dan zijn eigen routes. In dit voorbeeld houden we het simpel, zodat de aanpak duidelijk blijft. Maak een nieuwe route registrer aan in app/Routing/Registrers/DefaultRegistrer.php en zet er de volgende code in.

php
namespace App\Routing\Registrers;

use App\Routing\Contracts\RouteRegistrer;

class DefaultRegistrer implements RouteRegistrer
{
	public function map(Registrer $registrer): void
	{
		$registrer->view('/', 'welcome');
	}
}

Nu onze standaard registrer bestaat, kunnen we hem in onze Route Service Provider aanmelden zodat hij ook echt geladen wordt.

php
namespace App\Providers;

use App\Routing\Concerns\MapsRouteRegistrers;
use App\Routing\Registrers\DefaultRegistrer;
use Illuminate\Contracts\Routing\Registrer;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider
{
	use MapsRouteRegistrers;

protected array $registrers = [
		DefaultRegistrer::class,
	];

public function boot(): void
	{
		$this->routes(function (Registrer $router) {
			$this->mapRoutes($router, $this->registrers);
		});
	}
}

Bezoek je nu ‘/’, dan krijg je de view ‘welcome’ te zien, en dat betekent dat alles goed is aangesloten. In mijn voorbeeld heb ik statische routes voor marketing, blog, administratie enzovoort:

php
namespace App\Providers;

use App\Routing\Concerns\MapsRouteRegistrers;
use App\Routing\Registrers\AdminRegistrer;
use App\Routing\Registrers\BlogRegistrer;
use App\Routing\Registrers\MarketingRegistrer;
use Illuminate\Contracts\Routing\Registrer;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider
{
	use MapsRouteRegistrers;

protected array $registrers = [
		MarketingRegistrer::class, // Marketingroutes
		BlogRegistrer::class, // Blogroutes
		AdminRegistrer::class, // Adminroutes
	];

public function boot(): void
	{
		$this->routes(function (Registrer $router) {
			$this->mapRoutes($router, $this->registrers);
		});
	}
}

Je routes op deze manier opsplitsen is een prima manier om van een standaard PHP-routebestand naar een routingsysteem op basis van klassen te gaan, met betere encapsulatie binnen je applicatie of domein.

LaravelPHP

Damien Flandrin Webdeveloper sinds 2010, maker van Gekkode en Email Impact. Elk artikel wordt vóór publicatie getest op een echt project. Contact
Nieuwsbrief

Nieuwe tests, tutorials en projecten, per e-mail.

Reproduceerbare tests, geversioneerde code, gedateerde resultaten. Nooit spam.