Идёт обновление сайта. Несколько дней возможны сбои в оформлении и переводах. Документация работает — если страница выглядит сломанной, обновите её позже.

Документация
L Laravel L intervention/image
Войти
Главная Laravel 10.x Разработка пакетов

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

10.x 7 мар 2026 г.

#Введение

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

Существуют разные типы пакетов. Некоторые пакеты являются автономными, то есть работают с любым 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 вашего сервис-провайдера:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../config/courier.php' => config_path('courier.php'),
    ]);
}

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

$value = config('courier.option');
Внимание

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

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

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

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

/**
 * Register any application services.
 */
public function register(): void
{
    $this->mergeConfigFrom(
        __DIR__.'/../config/courier.php', 'courier'
    );
}
Внимание

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

#Маршруты

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

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadRoutesFrom(__DIR__.'/../routes/web.php');
}

#Миграции

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

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
}

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

#Файлы локализации

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

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
}

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

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

Вы можете зарегистрировать JSON-файлы перевода для вашего пакета с помощью метода loadJsonTranslationsFrom. Этот метод принимает путь к директории с JSON-файлами перевода вашего пакета:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadJsonTranslationsFrom(__DIR__.'/../lang');
}

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

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

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');

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

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

#Представления

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

/**
 * Bootstrap any package services.
 */
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 принимает массив путей к представлениям пакета и их желаемых мест публикации:

/**
 * Bootstrap the package services.
 */
public function boot(): void
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');

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

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

#Компоненты представлений

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

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

/**
 * Bootstrap your package's services.
 */
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;

/**
 * Bootstrap your package's services.
 */
public function boot(): void
{
    Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

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

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

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

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

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

<x-courier::alert />

#Artisan-команда «about»

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

use Illuminate\Foundation\Console\AboutCommand;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);
}

#Команды

Чтобы зарегистрировать Artisan-команды вашего пакета в Laravel, используйте метод commands. Он принимает массив имён классов команд. После регистрации команды можно запускать через CLI Artisan:

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

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            InstallCommand::class,
            NetworkCommand::class,
        ]);
    }
}

#Публичные ассеты

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

/**
 * Bootstrap any package services.
 */
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 сервис-провайдера:

/**
 * Bootstrap any package services.
 */
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