1. Глубже в детали
  2. Разработка пакетов

Введение

Пакеты - основной способ добавления функциональности в Laravel. Пакеты могут представлять собой что угодно, от отличного способа работы с датами, такого как Carbon, до пакета, который позволяет ассоциировать файлы с моделями Eloquent, такого как Laravel Media Library.

Существуют разные типы пакетов. Некоторые пакеты являются автономными, что означает, что они работают с любым PHP-фреймворком. Примерами автономных пакетов являются Carbon и PHPUnit. Любой из этих пакетов можно использовать с Laravel, указав их в файле composer.json.

С другой стороны, некоторые пакеты предназначены исключительно для использования с Laravel. Эти пакеты могут содержать маршруты, контроллеры, представления и конфигурацию, специально предназначенные для улучшения приложения Laravel. Этот руководство в первую очередь охватывает разработку пакетов, специфичных для Laravel.

Примечание о фасадах

При написании приложения Laravel обычно не имеет значения, используете ли вы контракты или фасады, поскольку оба обеспечивают примерно равные уровни тестируемости. Однако при написании пакетов ваш пакет обычно не будет иметь доступ ко всем вспомогательным средствам тестирования Laravel. Если вы хотите иметь возможность писать тесты для пакета, как если бы пакет был установлен в типичное приложение Laravel, вы можете использовать пакет Orchestral Testbench.

Обнаружение пакетов

В файле конфигурации приложения Laravel config/app.php опция providers определяет список поставщиков служб, которые должны быть загружены Laravel. Когда кто-то устанавливает ваш пакет, вы обычно хотите, чтобы ваш поставщик службы был включен в этот список. Вместо того чтобы требовать от пользователей вручную добавлять ваш поставщик в список, вы можете определить его в разделе extra файла composer.json вашего пакета. Кроме поставщиков служб, вы также можете перечислить любые фасады, которые вы хотели бы зарегистрировать:

"extra": {
"laravel": {
"providers": [
"Barryvdh\\Debugbar\\ServiceProvider"
],
"aliases": {
"Debugbar": "Barryvdh\\Debugbar\\Facade"
}
}
},

После того как ваш пакет будет настроен для автоматического обнаружения, Laravel автоматически зарегистрирует его поставщики служб и фасады при установке, создав удобный опыт установки для пользователей вашего пакета.

Отказ от обнаружения пакета

Если вы являетесь потребителем пакета и хотите отключить обнаружение пакета, вы можете перечислить имя пакета в разделе extra файла composer.json вашего приложения:

"extra": {
"laravel": {
"dont-discover": [
"barryvdh/laravel-debugbar"
]
}
},

Вы можете отключить обнаружение пакетов для всех пакетов, используя символ * внутри директивы dont-discover вашего приложения:

"extra": {
"laravel": {
"dont-discover": [
"*"
]
}
},

Поставщики служб

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

Поставщик службы расширяет класс Illuminate\Support\ServiceProvider и содержит два метода: register и boot. Базовый класс ServiceProvider находится в пакете Composer illuminate/support, который вы должны добавить в зависимости вашего собственного пакета. Чтобы узнать больше о структуре и назначении поставщиков служб, ознакомьтесь с их документацией.

Ресурсы

Конфигурация

Обычно вам нужно опубликовать файл конфигурации вашего пакета в каталог config приложения. Это позволит пользователям вашего пакета легко переопределять ваши настройки конфигурации по умолчанию. Чтобы позволить публикацию ваших файлов конфигурации, вызовите метод publishes из метода boot поставщика службы:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->publishes([
__DIR__.'/../config/courier.php' => config_path('courier.php'),
]);
}

Теперь, когда пользователи вашего пакета выполняют команду vendor:publish Laravel, ваш файл будет скопирован в указанное место публикации. После публикации конфигурации ее значения могут быть получены так же, как и у любого другого файла конфигурации:

$value = config('courier.option');

Внимание Не следует определять замыкания в файлах конфигурации. Их нельзя правильно сериализовать при выполнении команды Artisan config:cache.

Конфигурация пакета по умолчанию

Вы также можете объединить файл конфигурации вашего пакета с опубликованной копией приложения. Это позволит вашим пользователям определять только те параметры, которые они действительно хотят переопределить в опубликованной копии файла конфигурации. Для объединения значений файла конфигурации используйте метод mergeConfigFrom в методе register вашего поставщика служб.

Метод mergeConfigFrom принимает путь к файлу конфигурации вашего пакета в качестве первого аргумента и имя копии файла конфигурации приложения в качестве второго аргумента:

/**
* Регистрация любых служб приложения.
*/
public function register(): void
{
$this->mergeConfigFrom(
__DIR__.'/../config/courier.php', 'courier'
);
}

Внимание Этот метод объединяет только первый уровень массива конфигурации. Если ваши пользователи частично определяют многомерный массив конфигурации, отсутствующие опции не будут объединены.

Маршруты

Если ваш пакет содержит маршруты, вы можете загружать их, используя метод loadRoutesFrom. Этот метод автоматически определит, кешированы ли маршруты приложения, и не будет загружать ваш файл маршрутов, если маршруты уже были кешированы:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
}

Миграции

Если ваш пакет содержит миграции базы данных, вы можете использовать метод loadMigrationsFrom, чтобы сообщить Laravel, как их загрузить. Метод loadMigrationsFrom принимает путь к миграциям вашего пакета в качестве единственного аргумента:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
}

После того как миграции вашего пакета зарегистрированы, они будут автоматически запущены при выполнении команды php artisan migrate. Вам не нужно экспортировать их в каталог database/migrations приложения.

Файлы языка

Если ваш пакет содержит файлы языка, вы можете использовать метод loadTranslationsFrom, чтобы сообщить Laravel, как их загрузить. Например, если ваш пакет называется courier, вы должны добавить следующее в метод boot вашего поставщика служб:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
}

Строки перевода пакета ссылаются с использованием синтаксиса package::file.line. Так что вы можете загрузить строку welcome пакета courier из файла messages следующим образом:

echo trans('courier::messages.welcome');

Публикация файлов языка

Если вы хотите опубликовать файлы языка вашего пакета в каталог lang/vendor приложения, вы можете использовать метод publishes поставщика служб. Метод publishes принимает массив путей к пакетам и их желаемых мест публикации. Например, чтобы опубликовать файлы языка для пакета courier, вы можете сделать следующее:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
 
$this->publishes([
__DIR__.'/../lang' => $this->app->langPath('vendor/courier'),
]);
}

Теперь, когда пользователи вашего пакета выполняют команду vendor:publish Artisan Laravel, файлы языка вашего пакета будут опубликованы в указанное место публикации.

Шаблоны

Чтобы зарегистрировать шаблоны представлений вашего пакета с Laravel, вам нужно сообщить Laravel, где находятся представления. Вы можете сделать это, используя метод loadViewsFrom поставщика служб. Метод loadViewsFrom принимает два аргумента: путь к вашим шаблонам представлений и имя вашего пакета. Например, если ваш пакет называется courier, вы добавите следующее в метод boot вашего поставщика служб:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');
}

Шаблоны пакета обращаются с использованием синтаксиса package::view. Поэтому, после того как ваш путь к представлению зарегистрирован в поставщике службы, вы можете загрузить представление dashboard из пакета courier следующим образом:

Route::get('/dashboard', function () {
return view('courier::dashboard');
});

Переопределение шаблонов пакета

Когда вы используете метод loadViewsFrom, Laravel фактически регистрирует два места для ваших представлений: каталог resources/views/vendor приложения и указанный вами каталог представлений пакета. Таким образом, используя пакет courier в качестве примера, Laravel сначала проверит, размещен ли пользовательская версия представления в каталоге resources/views/vendor/courier разработчиком. Затем, если представление не было настроено, Laravel будет искать каталог представлений пакета, указанный вами при вызове loadViewsFrom. Это делает легким настраивание / переопределение представлений вашего пакета для пользователей пакета.

Публикация шаблонов

Если вы хотите сделать свои представления доступными для публикации в каталоге resources/views/vendor приложения, вы можете использовать метод publishes поставщика службы. Метод publishes принимает массив путей к представлениям пакета и их желаемых мест публикации:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');
 
$this->publishes([
__DIR__.'/../resources/views' => resource_path('views/vendor/courier'),
]);
}

Теперь, когда пользователи вашего пакета выполняют команду vendor:publish Artisan Laravel, представления вашего пакета будут скопированы в указанное место публикации.

Компоненты шаблонов

Если вы создаете пакет, который использует компоненты Blade или размещает компоненты в нестандартных каталогах, вам нужно вручную зарегистрировать класс компонента и его псевдоним тега HTML, чтобы Laravel знал, где их найти. Обычно вы регистрируете компоненты в методе boot поставщика служб вашего пакета:

use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;
 
/**
* Загрузка служб вашего пакета.
*/
public function boot(): void
{
Blade::component('package-alert', AlertComponent::class);
}

После того как ваш компонент зарегистрирован, его можно отрисовать с использованием его псевдонима тега:

<x-package-alert/>

Автозагрузка компонентов пакета

В качестве альтернативы вы можете использовать метод componentNamespace для автоматической загрузки классов компонентов по соглашению. Например, пакет Nightshade может содержать компоненты Calendar и ColorPicker, которые находятся в пространстве имен Nightshade\Views\Components:

use Illuminate\Support\Facades\Blade;
 
/**
* Загрузка служб вашего пакета.
*/
public function boot(): void
{
Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

Это позволит использовать компоненты пакета с использованием синтаксиса package-name:::

<x-nightshade::calendar />
<x-nightshade::color-picker />

Blade автоматически определит класс, связанный с этим компонентом, преобразовав имя компонента в паскаль-кейс. Поддерживаются также подкаталоги с использованием записи "точка".

Анонимные компоненты

Если ваш пакет содержит анонимные компоненты, их нужно разместить в каталоге components каталога "views" вашего пакета (как указано в методе loadViewsFrom). Затем их можно отрисовать, добавив префикс с пространством имен представления пакета:

<x-courier::alert />

Команда "О пакете" Artisan

Встроенная команда Artisan about предоставляет сводку среды и конфигурации приложения. Пакеты могут добавлять дополнительную информацию в вывод этой команды с использованием класса AboutCommand. Обычно эту информацию можно добавить из метода boot поставщика служб вашего пакета:

use Illuminate\Foundation\Console\AboutCommand;
 
/**
* Загрузка служб любого приложения.
*/
public function boot(): void
{
AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);
}

Команды

Чтобы зарегистрировать команды Artisan вашего пакета с Laravel, вы можете использовать метод commands. Этот метод ожидает массив имен классов команд. После регистрации команд их можно выполнять с использованием Artisan CLI:

use Courier\Console\Commands\InstallCommand;
use Courier\Console\Commands\NetworkCommand;
 
/**
* Загрузка служб пакета.
*/
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->commands([
InstallCommand::class,
NetworkCommand::class,
]);
}
}

Публичные ресурсы

Ваш пакет может содержать ресурсы, такие как JavaScript, CSS и изображения. Чтобы опубликовать эти ресурсы в каталог public приложения, используйте метод publishes поставщика службы. В этом примере мы также добавим тег группы public, который можно использовать для легкой публикации связанных групп ресурсов:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->publishes([
__DIR__.'/../public' => public_path('vendor/courier'),
], 'public');
}

Теперь, когда пользователи вашего пакета выполняют команду vendor:publish, ваши ресурсы будут скопированы в указанное место публикации. Поскольку пользователям часто нужно перезаписывать ресурсы при каждом обновлении пакета, вы можете использовать флаг --force:

php artisan vendor:publish --tag=public --force

Публикация групп файлов

Возможно, вам захочется публиковать группы ресурсов пакета отдельно. Например, вы можете разрешить пользователям публиковать файлы конфигурации вашего пакета, не заставляя публиковать ресурсы пакета. Это можно сделать, "маркируя" их при вызове метода publishes поставщика службы пакета. Например, давайте использовать теги для определения двух групп публикации для пакета courier (courier-config и courier-migrations) в методе boot поставщика службы пакета:

/**
* Загрузка служб пакета.
*/
public function boot(): void
{
$this->publishes([
__DIR__.'/../config/package.php' => config_path('package.php')
], 'courier-config');
 
$this->publishes([
__DIR__.'/../database/migrations/' => database_path('migrations')
], 'courier-migrations');
}

Теперь ваши пользователи могут публиковать эти группы отдельно, обращаясь к их тегу при выполнении команды vendor:publish:

php artisan vendor:publish --tag=courier-config