Введение
Пакеты (packages) — основной способ добавления нового функционала в Laravel. Пакеты могут быть всем, чем угодно — от классов для удобной работы с датами типа Carbon до целых библиотек BDD-тестирования наподобие Behat.
Конечно, всё это разные типы пакетов. Некоторые пакеты самостоятельны, что позволяет им работать в составе любой библиотеки, а не только Laravel. Примерами таких отдельных пакетов являются Carbon и Behat. Любая из них может быть использована в Laravel после простого их указания в файле composer.json.
С другой стороны, некоторые пакеты разработаны специально для использования в Laravel. В предыдущей версии Laravel такие пакеты назывались bundles. Они могли содержать маршруты, контроллеры, шаблоны, настройки и миграции, специально рассчитанные для улучшения приложения на Laravel.
Так как для разработки самостоятельных пакетов нет особенных правил, этот раздел документации в основном посвящён разработке именно пакетов для Laravel.
Все пакеты Laravel распространяются через Packagist и Composer, поэтому нужно изучить эти прекрасные средства распространения кода для PHP.
Создание пакета
Простейший способ создать пакет для использования в Laravel — с помощью команды workbench интерфейса Artisan. Сперва вам нужно установить несколько параметров в файле app/config/workbench.php. Там вы найдёте такие настройки как name и email. Их значения будут использованы при генерации composer.json для вашего нового пакета. Когда вы заполнили эти значения, то всё готово для создания заготовки.
Использование команды workbench
shphp artisan workbench vendor/package --resources
Имя поставщика (vendor) — способ отличить ваши собственные пакеты от пакетов других разработчиков. К примеру, если я, Тейлор Отуелл (автор Laravel — прим. пер.), хочу создать новый пакет под названием «Zapper», то имя поставщика может быть Taylor, а имя пакета — Zapper. По умолчанию команда PHPworkbench
сгенерирует заготовку в общепринятом стиле пакетов, однако команда resources может использоваться для генерации специфичных для Laravel папок, таких как migrations, views, config и прочих.
Когда команда workbench была выполнена, ваш пакет будет доступен в папке workbench текущей установки Laravel. Дальше вам нужно зарегистрировать PHPServiceProvider
— поставщика услуг, который был создан для нового пакета. Это можно сделать, добавив его к массиву providers файла app/config/app.php. Это укажет Laravel, что пакет должен быть загружен при запуске приложения. Имена классов поставщики услуг следуют схеме PHP[Package]ServiceProvider
. Таким образом, в примере выше мы должны были бы добавить PHPTaylor\Zapper\ZapperServiceProvider
к массиву providers.
Как только поставщик зарегистрирован вы готовы к началу разработки. Однако перед этим рекомендуется ознакомиться с материалом ниже, чтобы узнать о структуре пакетов и процессом их разработки.
Если ваш поставщик услуг не может быть найден, выполните команду shphp artisan dump-autoload
из корня вашего приложения.
Структура пакетов
При использовании команды workbench ваш пакет будет настроен согласно общепринятым нормам, что позволит ему успешно интегрироваться с другими частями Laravel.
Базовая структура папок внутри пакета
/src /Vendor /Package PackageServiceProvider.php /config /lang /migrations /views /tests /public
Давайте познакомимся с этой структурой поближе. Папка src/Vendor/Package — хранилище всех классов вашего пакета, включая PHPServiceProvider
. Папки config, lang, migrations и views содержат соответствующие ресурсы для вашего пакета (!!(tl_note)настройки, языковые строки, миграции и шаблоны — прим. пер.). Пакеты, как и обычные приложения, могут содержать любой из этих ресурсов.
Поставщики услуг
Поставщик услуг — просто начальный загрузчик для пакета. По умолчанию они могут содержать два метода: PHPboot()
и PHPregister()
. Внутри этих методов вы можете выполнять любой код — подключать файл с маршрутами, регистрировать связи в контейнере IoC, устанавливать обработчики событий или что-то ещё.
Метод PHPregister()
вызывается сразу после регистрации поставщика услуг, тогда как команда PHPboot()
вызывается только перед тем, как будет обработан запрос. Таким образом, если вашему поставщику требуется другой поставщик, который уже был зарегистрирован, или вы перекрываете услуги, зарегистрированные другим поставщиком — вам нужно использовать метод PHPboot()
.
При создании пакета с помощью команды workbench, метод PHPboot()
уже будет содержать одно действие:
$this->package('vendor/package');
Этот метод позволяет Laravel определить, как правильно загружать шаблоны, настройки и другие ресурсы вашего приложения. Обычно вам не требуется изменять эту строку, так как она настраивает пакет в соответствии с обычными нормами.
По умолчанию после регистрации пакета его ресурсы будут доступны через часть package из пары vendor/package. Однако, вы можете передать второй аргумент в метод PHPpackage()
, чтобы переопределить это поведение. Например:
// Передача пользовательского пространства имён (custom namespace) в метод package
$this->package('vendor/package', 'custom-namespace');
// Ресурсы пакета теперь доступны через custom-namespace
$view = View::make('custom-namespace::foo');
Для поставщиков услуг не существует «места по умолчанию». Вы можете поместить их в любое место, возможно, сгруппировав в пространство имён PHPProviders
в папке app. Этот файл может располагаться где угодно — главное, чтобы Composer мог загрузить его с помощью auto-loading facilities.
добавлено в 4.1 ()
Если вы изменили расположение ресурсов вашего пакета, таких как файлы конфигурации или представления, вы должны передать третий аргумент в метод PHPpackage()
, который указывает на местоположение ваших ресурсов:
$this->package('vendor/package', null, '/path/to/resources');
Отложенные поставщики
Если вы создаёте поставщик услуг, который не регистрирует какие-либо ресурсы, такие как настройки или представления, вы можете сделать его «отложенным». Отложенный поставщик услуг загружается и регистрируется только тогда, когда одна из услуг, которые он предоставляет, на самом деле необходима IoC-контейнеру приложения. Если ни одна из услуг провайдера не требуется для прохождения данного запроса, поставщик вообще не загружается.
Чтобы отложить выполнение вашего поставщика услуг, установите его свойство defer в значение true:
protected $defer = true;
Затем вам надо переопределить метод PHPprovides()
из базового класса Illuminate\Support\ServiceProvider и возвратить массив всех привязок, которые ваш провайдер добавляет в IoC-контейнер. Например, если ваш провайдер регистрирует package.service и package.another-service в IoC-контейнере, то ваш метод PHPprovides()
должен выглядеть следующим образом:
public function provides()
{
return array('package.service', 'package.another-service');
}
Соглашения
При использовании ресурсов из пакета, таких как настройки или шаблоны, то для отделения имени пакета обычно используют двойное двоеточие (::).
return View::make('package::view.name');
Чтение параметров настройки в пакете
return Config::get('package::group.option');
Внимание: если ваш пакет содержит миграции, подумайте о том, чтобы её имя начиналось с имени пакета для предотвращения возможных конфликтов с именами классов в других пакетах.
Процесс разработки
При разработке пакета бывает удобно работать в контексте вашего приложения, просматривая и экспериментируя с шаблонами и пр. Для начала сделайте чистую установку Laravel, затем используйте команду workbench для создания структуры пакета.
После того, как пакет создан вы можете сделать shgit init
изнутри папки workbench/[vendor]/[package], а затем — shgit push
для отправки пакета напрямую в хранилище. Это позволит вам удобно работать в среде приложения без необходимости постоянно выполнять команду shcomposer update
.
Теперь, когда ваши пакеты расположены в папке workbench, у вас может возникнуть вопрос: как Composer узнает, каким образом загружать эти пакеты? Laravel автоматически сканирует папку workbench на наличие пакетов, загружая их файлы при запуске приложения.
Если вам нужно зарегистрировать файлы автозагрузки вашего пакета, можно использовать команду shphp artisan dump-autoload
. Эта команда пересоздаст файлы автозагрузки для корневого приложения, а также всех пакетов в workbench, которые вы успели создать.
Выполнение команды автозагрузки
shphp artisan dump-autoload
Маршрутизация в пакетах
В предыдущей версии Laravel для указания URL, принадлежащих пакету, использовался параметр handles. Начиная с Laravel 4 пакеты могут обрабатывать любой URI. Для загрузки файлов с маршрутами просто подключите его через PHPinclude
из метода PHPboot()
вашего поставщика услуг.
Подключение файла с маршрутами из поставщика услуг
public function boot()
{
$this->package('vendor/package');
include __DIR__.'/../../routes.php';
}
Если ваш поставщик использует контроллеры, вам нужно убедиться, что они верно настроены в секции автозагрузки вашего файла composer.json.
Настройки пакетов
Некоторые пакеты могут требовать файлов настройки. Эти файлы должны быть определены аналогично файлам настроек обычного приложения. И затем, при использовании стандартной команды для регистрации ресурсов пакета PHP$this->package()
, они будут доступны через обычный синтаксис с двойным равно (::) :
Config::get('package::file.option');
Чтение параметров из единственного файла настроек
Однако если ваш пакет содержит всего один файл с настройками, вы можете назвать его config.php. Когда это сделано, то его параметры становятся доступными напрямую, без указания имени файла:
Config::get('package::option');
Ручная регистрация пространства имён ресурсов
Иногда вам может быть нужно зарегистрировать ресурсы пакета вне обычного вызова PHP$this->package()
. Обычно это требуется, если ресурс расположен не в стандартном месте. Для регистрации ресурса вручную вы можете использовать методы PHPaddNamespace()
классов PHPView
, PHPLang
и PHPConfig
:
View::addNamespace('package', __DIR__.'/path/to/views');
Как только пространство имён было зарегистрировано, вы можете использовать его имя и двойное двоеточие для получения доступа к ресурсам:
return View::make('package::view.name');
Параметры методов PHPaddNamespace()
одинаковы для классов PHPView
, PHPLang
и PHPConfig
.
Перекрытие файлов настроек
Когда другие разработчики устанавливают ваш пакет им может потребоваться перекрыть некоторые из настроек. Однако если они сделают это напрямую в коде вашего пакета, изменения будут потеряны при следующем обновлении пакета через Composer. Вместо этого нужно использовать команду config:publish интерфейса Artisan:
php artisan config:publish vendor/package
Эта команда скопирует файлы настроек вашего приложения в папку app/config/packages/vendor/package, где разработчик может их безопасно изменять.
Разработчик также может создать настройки, специфичные для каждой среды, поместив их в app/config/packages/vendor/package/environment.
добавлено в 4.1 ()
Представления пакетов
Когда вы используете пакет в вашем приложении, вам может захотеться настроить его представления. Вы легко можете экспортировать представления пакета в вашу папку app/views с помощью Artisan-команды shview:publish
:
php artisan view:publish vendor/package
Эта команда переместит представления пакета в папку app/views/packages. Если эта папка не существует, она будет создана при запуске команды. После того, как представления будут опубликованы, вы можете настроить их на свой вкус! Экспортированные представления автоматически получат приоритет над собственными файлами представлений пакета.
Миграции пакетов
Создание миграций для пакета в workbench
Вы можете легко создавать и выполнять миграции для любого из ваших пакетов. Для создания миграции в workbench используется команда --bench:
shphp artisan migrate:make create_users_table --bench="vendor/package"
Выполнение миграций пакета в workbench
shphp artisan migrate --bench="vendor/package"
Выполнение миграций установленного пакета
Для выполнения миграции для законченного пакета, который был установлен через Composer в папку vendor, вы можете использовать ключ --package:
shphp artisan migrate --package="vendor/package"
Внешние ресурсы пакетов
Перемещение ресурсов пакета в папку public
Некоторые пакеты могут содержать внешние ресурсы, такие как JavaScript-код, CSS и изображения. Однако мы не можем обращаться к ним напрямую через папки vendor и workbench, поэтому нам нужно перенести их в папку public нашего приложения. Команда asset:publish выполнит это за вас:
shphp artisan asset:publish php artisan asset:publish vendor/package
Если пакет находится в workbench, используйте ключ --bench:
shphp artisan asset:publish --bench="vendor/package"
Эта команда переместит ресурсы в public/packages в соответствии с именем поставщика и пакета. Таким образом, внешние ресурсы пакета userscape/kudos будут помещены в папку public/packages/userscape/kudos. Соблюдение этого соглашения о путях позволит вам использовать их в коде шаблонов вашего пакета.
Публикация пакетов
Когда ваш пакет готов к опубликованию, вам нужно отправить его в хранилище Packagist. Если пакет предназначен для Laravel рекомендуется добавить тег laravel в файл composer.json вашего пакета.
Также обратите внимание, что полезно присваивать вашим выпускам номера (tags), позволяя другим разработчикам использовать стабильные версии в их файлах composer.json. Если стабильный выпуск ещё не готов, можно добавить директиву Composer branch-alias.
Когда ваш пакет опубликован вы можете свободно продолжать его разработку в среде вашего приложения, созданной командой workbench. Это отличный способ, позволяющий удобно продолжать над ним работу даже после публикации.
Некоторые организации создают собственные частные хранилища пакетов для своих сотрудников. Если вам это требуется, изучите документацию проекта Satis, созданного командой разработчиков Composer.