Laravel-Routen in Klassen deklarieren statt in Routendateien

Laravel-Routen in Klassen deklarieren statt in Routendateien

In diesem Artikel zeige ich dir, wie du deine Routen sauber deklarierst, indem du sie in einer Klasse Route Registrers registrierst. Ein sauberer und einfacher Weg, Routen zu deklarieren.

Die Änderungen an deiner Laravel-Anwendung halten sich in Grenzen: Wir passen den Route Service Provider an und löschen die Routendateien für Web und API. Als Erstes legen wir einen neuen Trait/Concern mit dem Namen MapRouteRegistrers an, den wir in app/Providers/RouteServiceProvider einbinden. Füge diesem neuen Trait/Concern den folgenden Code hinzu.

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);
		}
	}
}

Wie du siehst, brauchen wir außerdem ein Interface beziehungsweise einen Contract, das alle unsere Registrers implementieren müssen.

Lege es unter App/Routing/Contracts/RouteRegistrer an und füge den folgenden Code hinzu.

php
namespace App\Routing\Contracts;

use Illuminate\Contracts\Routing\Registrer;

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

Trait und Interface stehen, jetzt sehen wir uns die Änderungen am Standard-Route-Service-Provider an.

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);
		});
	}
}

Im Code oben siehst du, dass wir unserem Route Service Provider eine neue Eigenschaft gegeben haben. In dieser Eigenschaft werden die Route-Registrer der Anwendung eingetragen und in der Boot-Methode geladen.

Unsere Anwendung ist jetzt bereit, Route-Registrer statt Routendateien zu verwenden. Legen wir also einen Standard-Registrer für die Anwendung an. Dieser Ansatz spielt seine Stärken besonders in einem modularen System oder in einem domänenorientierten Design aus, weil jede Domäne und jedes Modul seine eigenen Routen registrieren kann. Für dieses Beispiel bleiben wir einfach, damit der Ansatz klar wird. Lege einen neuen Route-Registrer unter app/Routing/Registrers/DefaultRegistrer.php an und füge den folgenden Code hinzu.

php
namespace App\Routing\Registrers;

use App\Routing\Contracts\RouteRegistrer;

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

Der Standard-Registrer steht, jetzt tragen wir ihn in unserem Route Service Provider ein, damit er auch wirklich geladen wird.

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);
		});
	}
}

Rufst du jetzt „/“ auf, bekommst du die View „welcome“ ausgeliefert: Alles ist also richtig verdrahtet. In meinem Beispiel habe ich statische Routen für Marketing, Blog, Administration und so weiter:

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, // Marketing-Routen
		BlogRegistrer::class, // Blog-Routen
		AdminRegistrer::class, // Admin-Routen
	];

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

Die Routen auf diese Weise aufzuteilen, ist ein ausgezeichneter Weg von der klassischen PHP-Routendatei hin zu einem klassenbasierten Routing, und damit zu einer deutlich besseren Kapselung in deiner Anwendung oder Domäne.

LaravelPHP

Damien Flandrin Webentwickler seit 2010, Gründer von Gekkode und Email Impact. Jeder Artikel wird vor der Veröffentlichung an einem echten Projekt getestet. Kontakt
Newsletter

Neue Tests, Tutorials und Projekte, per E-Mail.

Reproduzierbare Tests, versionierter Code, datierte Ergebnisse. Niemals Spam.