{{TOC}} {{DOCVER 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51, 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15, 5.1=cdc24ba7426c5b11eb4d050706bd78c3ea4913cc 19.06.2016 20:08:01, 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11}} == Введение == Пакеты (//packages//) - основной способ добавления нового функционала в Laravel. Пакеты могут быть всем, чем угодно - от классов для удобной работы с датами наподобие ((https://github.com/briannesbitt/Carbon Carbon)), до целых библиотек ((ВП:Бинарная диаграмма решений==BDD-тестирования)) наподобие ((https://github.com/Behat/Behat Behat)). Конечно, есть разные типы пакетов. Некоторые пакеты автономны, что позволяет им работать в составе любого PHP-фреймворка, не только Laravel. Примерами таких отдельных пакетов являются Carbon и Behat. Любой из них может быть использован в Laravel с помощью простого указания их в файле %%(t)composer.json%%. С другой стороны, некоторые пакеты разработаны специально для использования в Laravel. Они могут содержать ((docs/v5/routing маршруты)), ((docs/v5/controllers контроллеры)), ((docs/v5/views представления)) и ((docs/v5/configuration настройки)), специально рассчитанные для улучшения приложения на Laravel. Этот раздел документации в основном посвящён разработке именно пакетов для Laravel. Все пакеты Laravel распространяются через ((http://packagist.org/ Packagist)) и ((http://getcomposer.org/ Composer)), поэтому нужно изучить эти прекрасные средства распространения пакетов для PHP. %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51) === Замечание о фасадах === При создании Laravel-приложения в целом неважно, что использовать - контракты или фасады, поскольку и те и другие обеспечивают практически одинаковый уровень тестируемости. Но при создании пакетов лучше использовать ((//docs/v5/contracts контракты)), а не ((//docs/v5/facades фасады)). Поскольку у вашего пакета не будет доступа ко всем вспомогательным методам Laravel для тестирования, будет проще подменить или заглушить контракт, а не фасад. %% == Сервис-провайдеры == ((/docs/v5/providers Сервис-провайдеры)) - связующие элементы между вашим пакетом и Laravel. Они содержит привязки ((/docs/v5/container сервис-контейнера)), а также инструкции о том, где хранятся настройки пакета, его представления и языковые файлы. Сервис-провайдер наследует класс %%(t)Illuminate\Support\ServiceProvider%% и содержит два метода: %%register()%% и %%boot()%%. Базовый класс %%(t)ServiceProvider%% находится в пакете Composer %%(t)illuminate/support%%, который вы должны добавить в зависимости своего пакета. Подробнее о структуре и задачах сервис-провайдеров читайте в ((/docs/v5/providers документации)). == Маршруты == %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51) Чтобы определить маршруты для своего пакета, передайте файл маршрутов в метод %%loadRoutesFrom()%% из метода %%boot()%% сервис-провайдера вашего пакета. В этом файле вы можете использовать фасад %%(t)Illuminate\Support\Facades\Route%% для ((/docs/v5/routing регистрации маршрутов)), точно так же, как в обычном приложении Laravel: ~%% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { $this->loadRoutesFrom(__DIR__.'/path/to/routes.php'); } ~%% %% %%(DOCNEW 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15, 5.1=cdc24ba7426c5b11eb4d050706bd78c3ea4913cc 19.06.2016 20:08:01) Чтобы определить маршруты для своего пакета, просто затребуйте (%%require%%) файл маршрутов в методе %%boot()%% вашего сервис-провайдера. В этом файле вы можете использовать фасад %%(t)Route%% для ((/docs/v5/routing регистрации маршрутов)), точно так же, как в обычном приложении Laravel: ~%% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { if (! $this->app->routesAreCached()) { require __DIR__.'/../../routes.php'; } } ~%% %% %%(DOCNEW 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11) Чтобы загрузить файл маршрутов для вашего пакета, просто подключите его (include) в методе %%boot()%% вашего сервис-провайдера. ~%% public function boot() { include __DIR__.'/../../routes.php'; } ~%% .(alert) Если ваш пакет использует контроллеры, вам надо убедиться в том, что они правильно настроены в разделе автозагрузки файла %%(t)composer.json%%. %% == Ресурсы == === Настройки === В типичном случае вам потребуется опубликовать файл настроек вашего пакета в папку %%(t)config%% самого приложения. Это позволит пользователям вашего пакета легко изменять настройки по умолчанию. Чтобы позволить вашим файлам быть опубликованными, вызовите метод %%publishes()%% из метода %%boot()%% вашего сервис-провайдера: %% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { $this->publishes([ __DIR__.'/path/to/config/courier.php' => config_path('courier.php'), ]); } %% Теперь, когда пользователи вашего пакета вызовут команду Laravel %%(sh)vendor:publish%%, ваш файл будет скопирован в указанное место публикации. Само собой, когда ваш файл настроек опубликован, к его значениям можно обращаться как к любому другому файлу настроек: %% $value = config('courier.option'); %% **Настройки пакета по умолчанию** Вы также можете выбрать вариант соединения файла настроек вашего пакета с его копией в приложении. Это позволит вашим пользователям включать только те параметры, которые они хотят изменить в опубликованной копии конфигурации. Для объединения конфигураций используйте метод %%mergeConfigFrom()%% в методе %%register()%% вашего сервис-провайдера: %% /** * Регистрация привязок в контейнере. * * @return void */ public function register() { $this->mergeConfigFrom( __DIR__.'/path/to/config/courier.php', 'courier' ); } %% .(alert) Этот метод объединяет только первый уровень массива настроек. Если ваши пользователи определят многомерный массив настроек, отсутствующие параметры не будут объединены. %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51) === Миграции === Если ваш пакет содержит ((//docs/v5/migrations миграции БД)), вы можете использовать метод %%loadMigrationsFrom()%%, чтобы указать Laravel как их загружать. Метод %%loadMigrationsFrom()%% принимает единственный аргумент - путь к миграциям вашего пакета: ~%% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { $this->loadMigrationsFrom(__DIR__.'/path/to/migrations'); } ~%% После регистрации миграций вашего пакета они будут автоматически запущены при выполнении команды %%(sh)php artisan migrate%%. Вам не надо экспортировать их в основную папку приложения %%(t)database/migrations%%. %% === Переводы === Если ваш пакет содержит ((/docs/v5/localization языковые файлы)), вы можете использовать метод %%loadTranslationsFrom()%%, чтобы указать Laravel, как их загружать. Например, если ваш пакет называется %%(t)courier%%, вы можете добавить в метод %%boot()%% своего сервис-провайдера следующее: %% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier'); } %% На файлы переводов пакета ссылаются, используя синтаксис %%package::file.line%%. Поэтому вы можете загрузить строку %%(t)welcome%% пакета %%(t)courier%% из файла %%(t)messages%% таким образом: %% echo trans('courier::messages.welcome'); %% Помните, что в вашей папке с переводами должны быть подпапки для каждого языка, такие как %%(t)en%%, %%(t)es%%, %%(t)ru%% и т.д. **Публикация переводов** Для публикации переводов вашего пакета в папку %%(t)resources/lang/vendor%% приложения, используйте метод сервис-провайдера %%publishes()%%. Этот метод принимает массив путей к переводам пакета и предполагаемые места для их публикации. Например, для публикации языковых файлов пакета %%(t)courier%% сделайте так: %% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier'); $this->publishes([ __DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'), //для версии 5.1 и ранее: //__DIR__.'/path/to/translations' => base_path('resources/lang/vendor/courier'), ]); } %% Теперь, когда пользователи вашего пакета вызовут Artisan-команду Laravel %%(sh)vendor:publish%%, переводы вашего пакета будут скопированы в указанное место публикации. === Представления === Для регистрации ((/docs/v5/views представлений)) вашего пакета в Laravel, вам надо указать Laravel, где они расположены. Вы можете сделать это методом %%loadViewsFrom()%%. Этот метод принимает два аргумента: путь к шаблонам ваших представлений и название пакета. Например, если ваш пакет называется %%(t)courier%%, вам надо добавить в метод %%boot()%% своего сервис-провайдера следующее: %% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier'); } %% На представления пакета ссылаются, используя синтаксис %%package::view%%. Поэтому, когда путь вашего представления зарегистрирован в сервис-провайдере, вы можете загрузить представление %%(t)admin%% из пакета %%(t)courier%% таким образом: %% Route::get('admin', function () { return view('courier::admin'); }); %% **Переопределение представлений пакета** Когда вы используете метод %%loadViewsFrom()%%, на самом деле Laravel регистрирует два расположения для ваших представлений: в папке приложения %%(t)resources/views/vendor%% и в указанной вами папке. Поэтому в нашем примере с %%(t)courier%% Laravel сначала проверит, предоставил ли разработчик свою версию представления в %%resources/views/vendor/courier%%. Затем, если представление не было изменено, Laravel будет искать в вызове %%loadViewsFrom()%% указанную вами папку представлений пакета. Это упрощает редактирование или замену представлений вашего пакета для тех, кто им будет пользоваться. **Публикация представлений** Для публикации представлений вашего пакета в папку %%(t)resources/views/vendor%% используйте метод %%publishes()%% в методе %%boot()%% вашего сервис-провайдера. Метод %%publishes()%% принимает массив путей к представлениям пакета и предполагаемые места для их публикации. %% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier'); $this->publishes([ __DIR__.'/path/to/views' => resource_path('views/vendor/courier'), //для версии 5.1 и ранее: //__DIR__.'/path/to/views' => base_path('resources/views/vendor/courier'), ]); } %% Теперь, когда пользователи вашего пакета вызовут Artisan-команду Laravel %%(sh)vendor:publish%%, папка ваших представлений будет скопирована в указанное место публикации. %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51) == Команды == Для регистрации в Laravel Artisan-команд вашего пакета используйте метод %%commands()%%. Этот метод принимает массив имён классов команд. После регистрации команд вы можете выполнять их через ((//docs/v5/artisan консоль Artisan)): ~%% /** * Начальная загрузка сервисов приложения. * * @return void */ public function boot() { if ($this->app->runningInConsole()) { $this->commands([ FooCommand::class, BarCommand::class, ]); } } ~%% %% == Общие ресурсы == Ваш пакет может иметь ресурсы, такие как JavaScript, CSS и изображения. Для публикации этих ресурсов в папку приложения %%(t)public%% используйте метод %%publishes()%% в методе %%boot()%% вашего сервис-провайдера. В этом примере мы также добавим для ресурсов групповой тег "public", который можно использовать для публикации групп связанных ресурсов: %% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { $this->publishes([ __DIR__.'/path/to/assets' => public_path('vendor/courier'), ], 'public'); } %% Теперь, когда пользователи вашего пакета вызовут команду Laravel %%(sh)vendor:publish%%, ваши ресурсы будут скопированы в указанное место публикации. Поскольку обычно каждый раз при обновлении пакета вам необходимо перезаписать ресурсы, используйте флаг %%(sh)--force%%: %%(sh) php artisan vendor:publish --tag=public --force %% %%(DOCNEW 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15, 5.1=cdc24ba7426c5b11eb4d050706bd78c3ea4913cc 19.06.2016 20:08:01, 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11) Если вы хотите быть уверены, что ваши ресурсы всегда в актуальном состоянии, можете добавить эту команду в список %%(t)post-update-cmd%% в вашем файле %%(t)composer.json%%: %% == Публикация файлов по группам == Вам может пригодиться возможность публиковать отдельные группы файлов. Например, если вы захотите дать вашим пользователям возможность публиковать файлы настроек вашего пакета и файлы ресурсов по отдельности. Вы можете сделать это, присвоив им теги при вызове метода %%publishes()%% из сервис-провайдера пакета. Например, давайте используем теги для определения двух групп для публикации в методе %%boot()%% сервис-провайдера пакета: %% /** * Выполнение после-регистрационной загрузки сервисов. * * @return void */ public function boot() { // Публикация файла настроек $this->publishes([ __DIR__.'/../config/package.php' => config_path('package.php') ], 'config'); // Публикация ваших миграций $this->publishes([ __DIR__.'/../database/migrations/' => database_path('migrations') ], 'migrations'); } %% Теперь ваши пользователи могут публиковать эти группы отдельно, указывая их тег при выполнении команды %%(sh)vendor:publish%%: %%(sh) php artisan vendor:publish --tag=config %% %%(DOCNEW 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11) Если вы хотите перезаписать существующие файлы, используйте флаг %%(sh)--force%%: %%(sh) php artisan vendor:publish --force ~%% .(alert) **Внимание**: Вы можете использовать метод %%publishes()%% для публикации файлов **любых** типов в любое место. %%