Реализация модульной структуры в Laravel
Доброго времени суток. В данной статье мы реализуем модульность в Laravel. Да структура Laravel с ее пакетами удобна, но не всегда. Если наш проект разрастается до гигантских размеров, поддерживать код становится сложнее. Весь код, касающегося конкретного функционала, находится в разных местах. Контроллеры в папке Controllers. Модели в папке app. А вьюшки – во views. Можно конечно в этих каталогах создать подкаталоги, которые будут разделять код по функционалу. Но, на мой взгляд, это тоже не очень удобно. Гораздо наглядней, когда код функционала (например, реализация блога) находится в каталоге Modules/Blog. А уже все контроллеры (для реализации блога) находятся в каталоге Modules/Blog/Controllers. А модели соответственно в Modules/Blog/Models. И т.д. Даже скажу больше и роуты для нашего модуля будут находиться в файле Modules/Blog/Routes/routes.php. Интересно? Тогда приступим к реализации.
Для чего удобней использовать модули я описал во введении к статье. Первое, надо определиться, где будут расположены наши модули. Я предлагаю (и буду реализовывать), что модули будут располагаться в каталоге app/Modules. Каждый модуль будет располагаться в своем каталоге. Например, давайте реализуем модуль Test, задача, которого выводить на экран надпись «Test» (на английской локализации) и «Тест» (на русской локализации).
Давайте чуть подробней остановимся на структуре модуля.
Структура модуля Laravel
Как я описал выше, каждый модуль находится в собственном каталоге. Давайте создадим в app каталог для модулей Modules и уже в нем создадим каталог для модуля Test – «Test».
В каталоге Test создадим каталог «Controllers» в котором будут располагаться контроллеры нашего модуля.
В каталоге Test создадим каталог «Lang», в котором создадим два подкаталога «en» и «ru» (в соответствии с нашими локализациями), в которых будут находится файлы с переводами.
В каталоге Test создадим каталог «Migrtation», в котором будут лежать миграции для модуля.
В каталоге Test создадим каталог «Model» для моделей нашего модуля.
В каталоге Test создадим каталог «Routes» для файлов с роутами нашего модуля.
В каталоге Test создадим каталог «Views» для файлов со вьюшками нашего модуля.
Теперь необходимо создать файл в котором мы будем подключать модули к нашему проекту.
Файл конфигурации модулей Laravel
В каталоге config (где хранятся файлы конфигураций) создадим файл module.php. В этом файле будут храниться названия модулей, которые мы хотим загрузить. В этом же файле мы будем хранить и конфигурацию для модулей (но этом мы не будем останавливаться).
Листинг файла module.php
<?php return [ 'modules' => [ 'Test', ], ];
Следующим шагом нам необходимо создать Service Provider для внедрения системы модулей в Laravel.
Создание ServiceProvider для модулей в Laravel
Давайте в каталоге Modules создадим файл ModulesServiceProvider.php. Вот листинг файла:
<?php namespace App\Modules; /** * Сервис провайдер для подключения модулей */ class ModulesServiceProvider extends \Illuminate\Support\ServiceProvider { public function boot() { //получаем список модулей, которые надо подгрузить $modules = config("module.modules"); if($modules) { while (list(,$module) = each($modules)){ //Подключаем роуты для модуля if(file_exists(__DIR__.'/'.$module.'/Routes/routes.php')) { $this->loadRoutesFrom(__DIR__.'/'.$module.'/Routes/routes.php'); } //Загружаем View //view('Test::admin') if(is_dir(__DIR__.'/'.$module.'/Views')) { $this->loadViewsFrom(__DIR__.'/'.$module.'/Views', $module); } //Подгружаем миграции if(is_dir(__DIR__.'/'.$module.'/Migration')) { $this->loadMigrationsFrom(__DIR__.'/'.$module.'/Migration'); } //Подгружаем переводы //trans('Test::messages.welcome') if(is_dir(__DIR__.'/'.$module.'/Lang')) { $this->loadTranslationsFrom(__DIR__.'/'.$module.'/Lang', $module); } } } } public function register() { } }
Что такое Service Provider в Laravel вы можете прочитать в документации Laravel. В самом коде я оставил комментарии для пояснения что мы делаем. Также в комментариях примеры использования. Теперь нам осталось подключить наш сервис-провайдер. Для этого открываем файл config/app.php и добавляем следующий код:
'providers' => [ ... App\Modules\ModulesServiceProvider::class, ... ]
Все готово. Наш проект на Laravel имеет модульную систему. Давайте создадим модуль Test, который будет отображать надпись «Test» или «Тест» (в зависимости от локализации) при URL <наш сайт>/test. В моем случае это http://modul.loc/test
Создание модуля для Laravel
Структуру для модуля «Test» мы создали. Давайте создадим контроллер TestController в каталоге Controllers нашего модуля.
<?php namespace App\Modules\Test\Controllers; use App\Http\Controllers\Controller; class TestController extends Controller { public function index() { return view('Test::index'); } }
Работа с контроллерами и моделями в модуле ничем не отличается от использования стандартных контроллеров и моделей Laravel. Главное указать правильно пространство имен.
А вот использование вьюшек и файлов локализации отличается.
Для вывода вьюшки используется следующая структура view(‘<название модуля>::<название вьюшки>’)
Для вывода перевода используется trans(‘<Название модуля>::<файл переводов>.<фраза для перевода>’)
Теперь создадим вьюшку index.blade.php в каталоге Views нашего модуля.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Test</title> </head> <body> <h1>Наш модуль:</h1> {{ trans('Test::test.this_module')}} </body> </html>
Создадим два файла переводов test.php для русской локализации и английской.
Листинг файла Lang/en/test.php
<?php return [ 'this_module' => 'This module', ];
Листинг файла Lang/ru/test.php
<?php return [ 'this_module' => 'Это модуль', ];
Осталось только создать маршрут. В файл Routes/routes.php добавим следующий код:
<?php Route::group( [ 'namespace' => 'App\Modules\Test\Controllers', 'as' => 'test.', ], function(){ Route::get('/test', ['uses' => 'TestController@index']); });
И последний штрих – необходимо добавить наш модуль в файл config/module.php для подключения модуля в нашем проекте.
<?php return [ 'modules' => [ 'Test', ], ];
Проверим. Переходим по адресу <сайт>/test
Видим вывод «Это модуль». Т.к. русская локализация. Изменим локализацию английскую. Для этого откроем файл config/app.php и изменим:
… 'locale' => 'ru', …
На:
… 'locale' => 'en', …
Проверяем.
Все работает.
И в дополнении к статье видео:
Заключение
Мы с вами реализовали модульную систему в Laravel. Теперь функционал нашего проекта можно разбить по модулям, а код относящийся к определенному функционалу находится в одном месте (каталоге модуля)
Чтобы не пропустить выхода новых статей подписываемя: VK, twitter, facebook. И канал на youtube
Все работает, но если у вас php 7.2, то надо заменить
if($modules) {
while (list(,$module) = each($modules)){
на
if($modules) {
foreach ($modules as $module){
Спасибо за статью, именно то что искал. Но появился вопрос: как быть с css и js? Хотелось бы их так же как и контроллеры, вьюхи и пр. в Modules/test хранить, чтобы потом можно было просто эту папку копировать в другие проекты
Разобрался. laravel mix
Подскажите пожалуйста, каким образом по ( laravel mix) css, js, vue.js подключить к модулю?
Добрый день.
Вот мой рабочий код:
Так просто и удобно. Эта *** должна была быть в Laravel по умолчанию.