Подписывайтесь на наш Telegram канал и будьте в курсе всех событий.
Поделитесь своим кодом и идеями!
Поделитесь своим кодом и идеями!

Разработка пакетов

Вы просматриваете документ для прошлой версии.
Рассмотрите возможность обновления вашего проекта до актуальной версии 11.x. Почему это важно?

Введение

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

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

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

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

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

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

Параметр providers конфигурационного файла config/app.php определяет список поставщиков служб, загружаемых 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 куда загружать ресурсы пакета, такие как шаблоны, файлы конфигурации и локализации.

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

Ресурсы

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

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

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

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

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

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

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

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

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

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

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

Маршруты

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

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

Миграции

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

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

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

Переводы

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

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

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

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

Публикация переводов

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

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

    $this->publishes([
        __DIR__.'/../resources/lang' => resource_path('lang/vendor/courier'),
    ]);
}

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

Шаблоны

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

/**
 * Загрузка любых служб пакета.
 *
 * @return void
 */
public function boot()
{
    $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 принимает массив, состоящий из пути к шаблону и желаемого места публикации:

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

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

    $this->publishes([
        __DIR__.'/../resources/views' => resource_path('views/vendor/courier'),
    ]);
}

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

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

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

use Courier\Components\Alert;
use Courier\Components\Button;

/**
 * Загрузка любых служб пакета.
 *
 * @return void
 */
public function boot()
{
    $this->loadViewComponentsAs('courier', [
        Alert::class,
        Button::class,
    ]);
}

После того как ваши компоненты шаблонов зарегистрированы в поставщике, вы можете ссылаться на них в своих шаблонах следующим образом:

<x-courier-alert />

<x-courier-button />

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

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

<x-courier::alert />

Команды

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

use Courier\Console\Commands\InstallCommand;
use Courier\Console\Commands\NetworkCommand;

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

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

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

/**
 * Загрузка любых служб пакета.
 *
 * @return void
 */
public function boot()
{
    $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 поставщика:

/**
 * Загрузка любых служб пакета.
 *
 * @return void
 */
public function boot()
{
    $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