Недавно я столкнулся с уникальным подходом к загрузке маршрутов в приложения Laravel, и я хотел поделиться этим с вами. Он позволяет создавать классы регистраторов маршрутов, в которых вы регистрируете свои маршруты. Я увидел это в пакете, который в настоящее время разрабатывается Ollie Read, и он привлек мое внимание как чистый и захватывающий способ регистрации маршрутов.
Изменения, необходимые для стандартного приложения Laravel, относительно просты. Мы вносим несколько изменений в поставщика услуг маршрутизации и удаляем веб-файлы маршрутов и файлы маршрутов API. Первое, что мы делаем, это создаем новую черту/беспокойство, которое мы можем добавить к нашему app/Providers/RouteServiceProvider
призванному MapRouteRegistrars
. Добавьте следующий код к этому новому признаку/проблеме.
declare(strict_types=1);
namespace App\Routing\Concerns;
use App\Routing\Contracts\RouteRegistrar;
use Illuminate\Contracts\Routing\Registrar;
use RuntimeException;
trait MapRouteRegistrars
{
protected function mapRoutes(Registrar $router, array $registrars): void
{
foreach ($registrars as $registrar) {
if (! class_exists($registrar) || ! is_subclass_of($registrar, RouteRegistrar::class)) {
throw new RuntimeException(sprintf(
'Cannot map routes \'%s\', it is not a valid routes class',
$registrar
));
}
(new $registrar)->map($router);
}
}
}
Как вы можете видеть, нам также необходимо создать интерфейс / контракт для использования и обеспечить его реализацию всеми нашими регистраторами. Создайте это в разделе app/Routing/Contracts/RouteRegistrar
и добавьте следующий код.
declare(strict_types=1);
namespace App\Routing\Contracts;
use Illuminate\Contracts\Routing\Registrar;
interface RouteRegistrar
{
public function map(Registrar $registrar): void;
}
Теперь, когда у нас есть черта и интерфейс, мы можем посмотреть на изменения, которые нам нужно внести в поставщика услуг маршрутизации по умолчанию.
declare(strict_types=1);
namespace App\Providers;
use App\Routing\Concerns\MapsRouteRegistrars;
use Illuminate\Contracts\Routing\Registrar;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
use MapsRouteRegistrars;
protected array $registrars = [];
public function boot(): void
{
$this->routes(function (Registrar $router) {
$this->mapRoutes($router, $this->registrars);
});
}
}
Из приведенного выше кода вы можете видеть, что мы добавили новое свойство к нашему поставщику услуг маршрутизации. В этом свойстве регистраторы маршрутов приложения регистрируются и загружаются внутри метода загрузки.
Теперь, когда наше приложение готово к использованию регистраторов маршрутов вместо файлов маршрутов, давайте создадим приложение по умолчанию для нашего приложения. Этот подход будет исключительно хорошо работать в управляемом доменом дизайне или модульной системе, позволяя каждому домену или модулю регистрировать свои маршруты. В этом примере мы сделаем это простым, чтобы вы могли понять подход. Создайте нового регистратора маршрутов app/Routing/Registrars/DefaultRegistrar.php
и добавьте следующий код.
declare(strict_types=1);
namespace App\Routing\Registrars;
use App\Routing\Contracts\RouteRegistrar;
class DefaultRegistrar implements RouteRegistrar
{
public function map(Registrar $registrar): void
{
$registrar->view('/', 'welcome');
}
}
Теперь, когда наш регистратор по умолчанию создан, мы можем зарегистрировать его в нашем поставщике услуг маршрутизации, обеспечив его загрузку.
declare(strict_types=1);
namespace App\Providers;
use App\Routing\Concerns\MapsRouteRegistrars;
use App\Routing\Registrars\DefaultRegistrar;
use Illuminate\Contracts\Routing\Registrar;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
use MapsRouteRegistrars;
protected array $registrars = [
DefaultRegistrar::class,
];
public function boot(): void
{
$this->routes(function (Registrar $router) {
$this->mapRoutes($router, $this->registrars);
});
}
}
Теперь, если вы посещаете /
, вы будете загружены welcome
видом, а это значит, что все подключено правильно. Я могу представить себе отличный способ, которым я мог бы использовать это в своем приложении, где у меня есть статические маркетинговые маршруты, маршруты блогов, маршруты администраторов и многое другое. В качестве примера я бы предположил, что поставщик услуг маршрутизации выглядит следующим образом:
declare(strict_types=1);
namespace App\Providers;
use App\Routing\Concerns\MapsRouteRegistrars;
use App\Routing\Registrars\AdminRegistrar;
use App\Routing\Registrars\BlogRegistrar;
use App\Routing\Registrars\MarketingRegistrar;
use Illuminate\Contracts\Routing\Registrar;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
use MapsRouteRegistrars;
protected array $registrars = [
MarketingRegistrar::class, // Marketing Routes
BlogRegistrar::class, // Blog Routes
AdminRegistrar::class, // Admin Routes
];
public function boot(): void
{
$this->routes(function (Registrar $router) {
$this->mapRoutes($router, $this->registrars);
});
}
}
Разделение наших маршрутов таким образом - отличный способ перейти от стандартного файла маршрутов PHP к системе маршрутизации на основе классов, позволяющей лучше инкапсуляцию с вашим приложением или доменом.
Какие еще способы помочь вам управлять растущим приложением? Особенно с точки зрения маршрутизации, они могут стать немного непослушными через некоторое время. Сообщите нам об этом в Твиттере.