Trasy w Laravelu deklarowane w klasach zamiast w plikach

Trasy w Laravelu deklarowane w klasach zamiast w plikach

W tym artykule pokazuję, jak porządnie deklarować trasy, tworząc klasy Route Registrers, w których je rejestrujesz. To czysty i prosty sposób na deklarowanie tras.

Zmiany, które trzeba wprowadzić w aplikacji Laravel, są dość proste. Modyfikujemy trochę service provider tras i usuwamy pliki tras Web oraz API. Na początek tworzymy nowy trait/concern, który dołożymy do app/Providers/RouteServiceProvider, o nazwie MapRouteRegistrers. Dodaj poniższy kod do nowego 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);
		}
	}
}

Jak widzisz, musimy też stworzyć interfejs/kontrakt i zadbać o to, żeby wszystkie nasze Registrers go implementowały.

Utwórz go w App/Routing/Contracts/RouteRegistrer i dodaj poniższy kod.

php
namespace App\Routing\Contracts;

use Illuminate\Contracts\Routing\Registrer;

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

Skoro trait i interfejs są już na miejscu, możemy przyjrzeć się zmianom, jakie trzeba wprowadzić w domyślnym service providerze routingu.

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

W powyższym kodzie widać, że do service providera tras doszła nowa właściwość. To w niej rejestrują się registrery tras aplikacji, ładowane potem w metodzie startowej.

Aplikacja jest już gotowa na registrery tras zamiast plików tras, więc utwórzmy dla niej jeden domyślny. To podejście sprawdza się wyjątkowo dobrze w systemie modularnym albo w projekcie zorientowanym na domeny, każda domena lub każdy moduł rejestruje wtedy własne trasy. W tym przykładzie zostaniemy przy najprostszej wersji, żeby samo podejście było jasne. Utwórz nowy registrer tras w app/Routing/Registrers/DefaultRegistrer.php i dodaj poniższy kod.

php
namespace App\Routing\Registrers;

use App\Routing\Contracts\RouteRegistrer;

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

Domyślny registrer jest gotowy, więc możemy zarejestrować go w Route Service Providerze, żeby mieć pewność, że zostanie załadowany.

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

Jeśli teraz wejdziesz na „/”, dostaniesz widok „welcome”, co oznacza, że wszystko jest poprawnie spięte. W moim przykładzie mam statyczne trasy marketingowe, trasy bloga, trasy panelu administracyjnego i tak dalej:

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, // Trasy marketingowe
		BlogRegistrer::class, // Trasy bloga
		AdminRegistrer::class, // Trasy panelu administracyjnego
	];

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

Rozbicie tras w ten sposób to świetny sposób na przejście ze zwykłego pliku tras w PHP na routing oparty na klasach, co daje dużo lepszą hermetyzację w obrębie aplikacji lub domeny.

LaravelPHP

Damien Flandrin Web developer od 2010 roku, twórca Gekkode i Email Impact. Każdy artykuł jest sprawdzany na prawdziwym projekcie przed publikacją. Kontakt
Newsletter

Nowe testy, poradniki i projekty — e-mailem.

Powtarzalne testy, wersjonowany kod, datowane wyniki. Nigdy spamu.