Skip to content

Latest commit

 

History

History
384 lines (293 loc) · 24.6 KB

packages.md

File metadata and controls

384 lines (293 loc) · 24.6 KB

Laravel 9 · Разработка пакетов

Введение

Пакеты – это основной способ добавления функциональности в 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__.'/../lang', 'courier');
}

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

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

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

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

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

    $this->publishes([
        __DIR__.'/../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 принимает массив, состоящий из пути к шаблону и желаемого места публикации:

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

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

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

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

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

use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;

/**
 * Загрузка служб вашего пакета.
 *
 * @return void
 */
public function boot()
{
    Blade::component('package-alert', AlertComponent::class);
}

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

<x-package-alert/>

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

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

use Illuminate\Support\Facades\Blade;

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

Это позволит использовать компоненты пакета в пространстве имен их поставщиков, используя синтаксис x-package-name:::

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

Blade автоматически обнаружит класс, связанный с этим компонентом, используя «регистр паскаля» имени компонента. Также поддерживаются подкаталоги с использованием «точечной» нотации.

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

Если ваш пакет содержит анонимные компоненты, то они должны быть помещены в каталог 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-config и courier-migrations для определения двух групп публикации в методе boot поставщика пакета courier:

/**
 * Загрузка любых служб пакета.
 *
 * @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