
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.
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.
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.
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.
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.
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:
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.


