Структурируем маршруты в крупных проектах на Laravel | OTUS

Курсы

Программирование
Java Developer. Professional Highload Architect C++ Developer. Basic Специализация C++ Developer C++ Developer. Professional Java Developer. Basic Kotlin Developer. Basic Microservice Architecture JavaScript Developer. Basic Cloud Solution Architecture Team Lead C# Developer. Professional Алгоритмы и структуры данных Rust Developer C# Developer. Basic NoSQL Выбор профессии в IT
-99%
Python Developer. Basic Python Developer. Professional Базы данных iOS Developer. Professional React.js Developer Scala-разработчик Специализация iOS Unity Game Developer. Basic Руководитель разработки Разработчик Android Последние изменения в Java AWS для разработчиков Разработчик программных роботов (RPA) на базе UiPath и PIX NOSQL CI/CD Kotlin Backend Developer Node.js Developer Специализация Java и Архитектор ПО Специализация PHP и Базы Данных Интенсив «Оптимизация в Java» Супер - интенсив по паттернам проектирования Теория Игр Супер - интенсив по Kubernetes Symfony Framework Advanced Fullstack JavaScript developer Супер-интенсив "Tarantool" Spring Framework для Diasoft Специализация PHP Developer PostgreSQL Cloud Solutions Golang Developer Буткемп Python Developer Angular Developer
Специализация Java-разработчик JavaScript Developer. Professional Android Developer. Professional Программист С HTML/CSS Специализация Fullstack developer Android Developer. Basic Специализация Android-разработчик Software Architect PostgreSQL для администраторов баз данных и разработчиков PHP Developer. Professional Web-разработчик на Python Agile Project Manager Unity Game Developer. Professional C# Developer Flutter Mobile Developer Разработчик на Spring Framework Специализация Python Developer Golang Developer. Professional Unreal Engine Game Developer. Basic Архитектура и шаблоны проектирования C# ASP.NET Core разработчик iOS Developer. Basic Computer Science VR/AR - разработчик Разработчик Java Enterprise MS SQL Server Developer Framework Laravel PostgreSQL Специализация Java-разработчик (консультации) Разработчик чат-ботов и приложений для виртуальных ассистентов Анализ данных и машинное обучение в MATLAB Vue.js разработчик VOIP инженер Специализация Java и Базы данных Специализацияz PHP Fullstack разработчик Программист 1С Разработчик децентрализованных систем Супер-практикум по использованию и настройке GIT Разработчик IoT Подготовка к сертификации Oracle Java Programmer (OCAJP) Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив Azure PHP Developer. Basic Буткемп Java Groovy Developer C# Developer Буткемп Frontend Developer
Инфраструктура
Highload Architect Дизайн сетей ЦОД DevOps 1C Microservice Architecture Software Architect Cloud Solution Architecture Внедрение и работа в DevSecOps Administrator Linux. Advanced DevOps практики и инструменты Network Security Network engineer SRE практики и инструменты Безопасность Linux PostgreSQL NOSQL CI/CD Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "SQL для анализа данных" Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс «Введение в непрерывную поставку на базе Docker» Специализация Network Engineer MongoDB AWS Cloud Developer
Корпоративные курсы
Machine Learning. Professional Spark Developer Дизайн сетей ЦОД Java QA Engineer. Basic Cloud Solution Architecture Пентест. Практика тестирования на проникновение Внедрение и работа в DevSecOps Выбор профессии в IT
-99%
DevOps практики и инструменты MLOps Game QA Engineer Цифровая подпись в ИБ Машинное обучение для обеспечения ИБ Компьютерная криминалистика (форензика) Безопасность компьютерных сетей Пентестинг мобильных приложений Руководитель ИБ Безопасность Linux Разработчик программных роботов (RPA) на базе UiPath и PIX Анализ данных и машинное обучение в MATLAB Практикум по Kali Linux Node.js Developer Супер-практикум по работе с протоколом BGP Интенсив «Оптимизация в Java» Программист 1С Супер - интенсив по паттернам проектирования Супер-практикум по использованию и настройке GIT Разработчик IoT Embedded-разработчик Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс "Версионирование и командная работа с помощью Git" Супер-интенсив Azure Интенсив AWS Data Engineer MongoDB b2b-webinar
Agile Project Manager Компьютерное зрение Руководитель поддержки пользователей в IT Reverse-Engineering Системный аналитик. Advanced NoSQL Системный аналитик. Basic Экспресс-курс «IaC Ansible» IT-Recruiter Enterprise Architect Экcпресс-курс «ELK» Пентест веб-приложений Разработчик блокчейн-проектов Безопасность приложений Криптографическая защита информации Безопасность информационных систем SRE практики и инструменты Защита персональных данных в корпоративных системах Разработчик чат-ботов и приложений для виртуальных ассистентов CTF по ИБ Специализация Реверс & Пентест VOIP инженер Супер-интенсив «Data Engineer» Infrastructure as a code Безопасность веб-приложений Теория Игр Супер - интенсив по Kubernetes Revit Супер-интенсив "SQL для анализа данных" Экспресс-курс «CI/CD» Экспресс-курс «Введение в непрерывную поставку на базе Docker» BPMN: Моделирование бизнес-процессов Основы Windows Server Вебинар CERTIPORT Python для аналитики
Специализации Курсы в разработке Подготовительные курсы Подписка
+7 499 938-92-02

Структурируем маршруты в крупных проектах на Laravel

Laravel_Deep_23.7_site-5020-86729a.png

Существуют проекты на Laravel с сотнями маршрутов и отдельными секциями для пользователей, гостей и администраторов. Хранить всё это в одном файле неразумно и неэффективно. Возникает вопрос, как маршруты сгруппировать и добавить префиксы в URL? В этой статье мы посмотрим, что можно сделать.

1. Разделяем WEB- и API-маршруты

Это совсем просто, ведь Laravel выполняет данную операцию по умолчанию. Можно создать 2 файла: — routes/web.php; — routes/api.php.

Если проект имеет и API-страницы и веб-страницы, поместите API-маршруты в отдельный файл. Представьте, что есть страница /users, а также конечная точка /api/users/. Если их разделить на отдельные файлы, вы не запутаетесь в одинаковых именах.

Однако структурирование делается по индивидуальным предпочтениям, 100%-го стандарта не существует. Доказательство этому — нелогичный пример в официальном Laravel-проекте Horizon у Тейлора. Проект имеет API-маршруты, но отдельный файл не используется — проекта помещён в route/web.php:

1-20219-ce473f.png

2. Структурируем файл routs/web.php в Группы

Группировка маршрутов тоже возможна в «базовом» Laravel. Вот пример из официальной документации:

Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// использует мидлвары first и second
});

Route::get('user/profile', function () {
// использует мидлвары first и second
});
});

Особенности применения — скрытие разных групп под различными мидлварами. К примеру, одну группу можно ограничить дефолтным auth-мидлваром, а другую — отдельным администраторским и т. п.

И можно использовать как имена, так и префиксы групп маршрутов. Вот ещё парочка примеров из официальной документации:

Route::prefix('admin')->group(function () {
Route::get('users', function () {
// Соответствует адресу "/admin/users"
});
});

Route::name('admin.')->group(function () {
Route::get('users', function () {
// Маршруту присваивается имя "admin.users"...
})->name('users');
});

Желаете добавить мидлвар+имя+префикс в одну группу? Сделайте их массивом, тогда их будет удобнее читать:

// Вместо такой цепочки
Route::name('admin.')->prefix('admin')->middleware('admin')->group(function () {
// ...
});

// Можно использовать массив
Route::group([
'name' => 'admin.', 
'prefix' => 'admin', 
'middleware' => 'auth'
], function () {
// ...
});

А теперь соединим всё в реальном примере: — Группа «Гость» без мидлвара и с адресами /front/XXXXX; — Группа «Пользователь» с auth-мидлваром и адресами /user/XXXXX; — Группа «Администратор» с отдельным admin-мидлваром и адресами /admin/XXXXX.

Выполняем группировку всего этого в файле routs/web.php:

Route::group([
'name' => 'admin.',
'prefix' => 'admin',
'middleware' => 'admin'
], function () {

// адрес: /admin/users
// имя маршрута: admin.users
Route::get('users', function () {
return 'Admin: user list';
})->name('users');

});

Route::group([
'name' => 'user.',
'prefix' => 'user',
'middleware' => 'auth'
], function () {

// адрес: /user/profile
// имя маршрута: user.profile
Route::get('profile', function () {
return 'User profile';
})->name('profile');

});

Route::group([
'name' => 'front.',
'prefix' => 'front'
], function () {

// без мидлвара
// адрес: /front/about-us
// имя маршрута: front.about
Route::get('about-us', function () {
return 'About us page';
})->name('about');

});

3. Группируем контроллеры с пространствами имён

В примере выше мы не использовали контроллеры, а возвращали статический текст. Можно добавить контроллеры с ещё одним «поворотом» — в результате получим структуризацию по папкам с их собственными пространствами имен:

2-20219-6b79a9.png

И сможем применить их в файле маршрутов:

Route::group([
'name' => 'front.',
'prefix' => 'front'
], function () {
Route::get('about-us', 'Front\[email protected]')->name('about');
});

Но что произойдёт, если в данной группе будет много контроллеров? Потребуется ли постоянно добавлять Front\SomeController? Разумеется, нет. Вы просто указываете пространство имен в виде одного из параметров.

Route::group([
'name' => 'front.',
'prefix' => 'front',
'namespace' => 'Front',
], function () {
Route::get('about-us', '[email protected]')->name('about');
Route::get('contact', '[email protected]')->name('contact');
});

4. Группа в группе

Указанная выше ситуация с 3-мя группами упрощена. В действительности реальные проекты отличаются немного другой структурой, включающей в себя 2 группы: front и auth. И внутри auth существуют подгруппы: user и admin . Можно создать подгруппы в routes/web.php, а потом назначить разные мидлвары/префиксы и т. п.

Route::group([
'middleware' => 'auth',
], function() {

Route::group([
'name' => 'admin.',
'prefix' => 'admin',
'middleware' => 'admin'
], function () {

// адрес: /admin/users
// имя маршрута: admin.users
Route::get('users', '[email protected]')->name('users');

});

Route::group([
'name' => 'user.',
'prefix' => 'user',
], function () {

// адрес: /user/profile
// имя маршрута: user.profile
Route::get('profile', '[email protected]')->name('profile');

});

});

Мало того, можно сделать более, чем 2 уровня, как в примере из открытого проекта Akaunting:

Route::group(['middleware' => 'language'], function () {
Route::group(['middleware' => 'auth'], function () {
Route::group(['prefix' => 'uploads'], function () {
Route::get('{id}', 'Common\[email protected]');
Route::get('{id}/show', 'Common\[email protected]');
Route::get('{id}/download', 'Common\[email protected]');
});

Route::group(['middleware' => 'permission:read-admin-panel'], function () {
Route::group(['prefix' => 'wizard'], function () {
Route::get('/', 'Wizard\[email protected]')->name('wizard.index');

// ...

Или из проекта Monica:

Route::middleware(['auth', 'verified', 'mfa'])->group(function () {
Route::name('dashboard.')->group(function () {
Route::get('/dashboard', '[email protected]')->name('index');
Route::get('/dashboard/calls', '[email protected]');
Route::get('/dashboard/notes', '[email protected]');
Route::get('/dashboard/debts', '[email protected]');
Route::get('/dashboard/tasks', '[email protected]');
Route::post('/dashboard/setTab', '[email protected]');
});

5. Глобальные настройки в RouteServiceProvider

Существует файл, настраивающий все маршруты — это app/Providers/RouteServiceProvider.php. В нём есть метод map(), благодаря которому оба файла маршрутов — web и API связываются:

public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}

protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}

protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}

Заметили ли вы, что в методах упоминается пространство имен, мидлвар и префикс? И здесь можно устанавливать глобальные настройки для маршрутов, тогда вам не придётся повторять их для каждой группы.

Как правило, данный файл используется для API-маршрутов, ведь их настройки обычно одинаковы:

protected function mapApiRoutes()
{
Route::group([
'middleware' => ['api'],
'namespace' => $this->namespace,
'prefix' => 'api/v1',
], function ($router) {
require base_path('routes/api.php');
});
}

А с помощью метода выше вы добавите префикс «api/v1/» для всех адресов API.

6. Группировка по файлам — стоит ли овчинка выделки?

Если у вас большое число маршрутов, и вы желаете ещё больше сгруппировать их в отдельные файлы, можно задействовать файл, упоминавшийся в предыдущем пункте — app/Providers/RouteServiceProvider.php.

Присмотревшись к методу map(), вы увидите в конце закомментированное место:

public function map()
{
$this->mapApiRoutes();

$this->mapWebRoutes();

//
}

Можно интерпретировать это, как в некотором роде «приглашение» и добавить ещё файлы, если пожелаете. Так вы сможете создать внутри файла ещё один метод, к примеру, mapAdminRoutes()с последующим добавлением его в метод map(). В итоге файл будет и зарегистрирован, и автоматически загружен.

С одной стороны, это даёт чуть большее разделение маршрутов, с другой — вы иногда теряетесь в этих файлах и пытаетесь вспомнить, где искать конкретный маршрут.

7. Находим точный маршрут с помощью Artisan route:list

В некоторых случаях нужный маршрут поможет найти artisan-команда. Скорее всего, вы в курсе, что php artisan route:list позволяет показать все маршруты в проекте:

3-20219-1e44a5.png

Но в курсе ли вы, что есть возможность фильтрации вывода с целью нахождения именно того, что надо? Для этого добавьте –method, либо –name, либо –path с параметрами.

Смотрим фильтрование по методу POST, GET, и т. д.

4-20219-1faaae.png

А вот фильтрование по части адреса или имени:

5-20219-16719f.png

Пожалуй, это всё, что можно рассказать о группировке маршрутов в крупных Laravel-проектах.

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться