Verification: a143cc29221c9be0

Php artisan vendor publish что это

Php artisan vendor publish что это

Содержание

Создаем новый проект на Laravel 5.5

Поскольку новый релиз еще не выпущен официально, мы можем пока скачать dev-релиз при помощи следующей команды:


laravel new laravel55 --dev
cd laravel55
php artisan key:generate

Если вы не любите Laravel installer, можете воспользоваться командой composer:


composer create-project --prefer-dist --stability=dev laravel/laravel:dev-master
cd laravel
php artisan key:generate

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


Рендерим Mailables в браузере

Мне кажется, эта фича будет очень полезной. В предыдущих версиях Laravel нам приходилось слать реальные письма или пользоваться email-клиентом вроде Mailtrap, чтобы протестировать рассылку, и задачка это была не самая веселая. Больше не надо страдать, в Laravel 5.5 теперь можно отрендерить шаблон письма прямо в браузере.

Вот быстрый способ, как это сделать: создаем новый mailable и шаблон письма для нашего проекта:


php artisan make:mail Welcome --markdown=emails.welcome

Я предпочитаю использовать формат markdown, поскольку мы получаем шаблон уже с каким-то контентом. Открываем файл web.php и создаем тестовый route, чтобы проверить шаблон письма:


Route::get('/email', function () {
    return new App\Mail\Welcome();
});

routes/web.php

Если мы зайдем в route /email, то мы сможем увидеть шаблон письма:

email template

На самом деле происходит следующее. В Laravel 5.5 класс ‘Mailable’ использует контракт ‘Renderable’ с методом ‘render()’. Вот реализация метода render в ‘Illuminate/Mail/Mailable.php’:


public function render()
{
    Container::getInstance()->call([$this, 'build']);

    return Container::getInstance()->make('mailer')->render(
        $this->buildView(), $this->buildViewData()
    );
}

Illuminate/Mail/Mailable.php

С помощью этого метода можно получить view. Если бы мы попытались вернуть экземпляр класса, который не применяет контракт ‘Renderable’ внутри наших route’ов, то мы бы получили ‘UnexpectedValueException’.


Кастомное оформление писем

Если использовать Markdown для оформления писем, то Laravel поставит дефолтную тему. Впрочем, кому-то могут потребоваться собственные стили, чтобы продвигать свой бренд.

Чтобы сделать кастомное оформление для конкретного mailable, сначала создаем кастомный файл ‘.css’ с нужными нам стилями:


touch resources/views/vendor/mail/html/themes/custom.css

Затем указываем имя этого файла в качестве характеристики класса Mailable:


class Welcome extends Mailable
{
    protected $theme = 'custom';
    [...]
}

app/Mail/Welcome.php

Таким образом, шаблон письма будет основываться на тех стилях, которые мы указали в файле custom.css. Что особенно радует, так это то, что мы можем задавать разные стили для разных mailable`ов.


Вспомогательные функции исключений

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

Посмотрим, как можно применять эти исключения:


$number = 2;
throw_if($number !== 3, new NotThreeException('Number is not three'));
// or
throw_if($number !== 3, NotThreeException::class, 'Number is not three');

Если использовать вспомогательную функцию ‘throw_if’, исключение будет выброшено при условии, что первый аргумент будет расценен как true.

Если использовать throw_unless, то по сути будет все то же самое, с тем лишь отличием, что исключение будет выброшено, если первый аргумент окажется false.


$number = 2;
throw_unless($number === 3, new NotThreeException('Number is not three'));
// or
throw_unless($number === 3, NotThreeException::class, 'Number is not three');

Не лучший пример, но для демонстрации подойдет.


Команда migrate:fresh

Вы, вероятно, оказывались в ситуации, когда вам приходилось восстанавливать базу данных. В предыдущих версиях Laravel это можно было сделать при помощи команды php artisan migrate:refresh. Команда migrate:refresh откатывает назад все миграции, основываясь на том, что описывается в ‘down’ методе каждого миграционного файла, а затем запускает миграции снова.

php artisan migrate refresh

Но у вас, возможно, пару раз случались проблемы с этой командой, особенно при работе с ограничениями внешнего ключа (foreign key constraints) или когда один из ‘down()’ методов в какой-либо из ваших миграций не был определен в достаточной мере. Когда такое происходит, мы в большинстве случаев вручную избавляемся от таблицы, с которой возникают проблемы — (возможно, используя CLI или какой-нибудь GUI). Вот именно тогда команда migrate:fresh спешит на помощь. Эта команда удаляет все таблицы, а затем снова запускает существующие миграции:

migrate-fresh


Stack Trace ошибок в формате JSON

Не самое большое изменение, но в предыдущих версиях Laravel мы видели HTML-разметку от клиента API вроде Postman каждый раз, когда возникала ошибка в наших API. В Laravel 5.5 в случае ошибки мы получаем не HTML-разметку, а трассировку в JSON, которую легче воспринимать:

Трассировка json


Автоматическая установка пакетов

Чтобы использовать сторонний пакет в наших проектах на Laravel, мы делаем следующее:


  • Устанавливаем пакет.
  • Регистрируем сервис-провайдер пакета.
  • Регистрируем фасады, если они есть.

Как видите, процедуру можно упростить. Теперь будет следующим образом.

С автоматической установкой пакетов мы просто выбираем нужный пакет и ставим его на лету. Замечу, впрочем, что это возможно, только если поставщик пакета настроил его соответствующим образом.

Если мы посмотрим на пакет Laravel Debugbar, для которого уже настроена автоустановка, мы увидим, что внутри файла composer.json есть секция extra:


"extra": {
    "laravel": {
        "providers": [
            "Foo\\Bar\\ServiceProvider"
        ],
        "aliases": {
            "Bar": "Foo\\Bar\\Facade"
        }
    }
}

Поставщикам пакетов надо будет добавить секцию extra в файл composer.json, а затем указать сервис-провайдеров и любые алиасы для пакета.

Еще один плюс автоустановки пакетов в том, что если удалить зависимость, то ничего не сломается. Обычно даже после сноса пакета его сервис-провайдеры и фасады все еще торчат в файле config/app.php, и в некоторых случаях из-за них могут возникать ошибки.

С автоустановкой, если удалить пакет через Composer, то удаляется также все, что связано с этим пакетом.


Изменения в команде vendor:publish

В предыдущих версиях Laravel команда vendor:publish публиковала ресурсы всех пакетов и самого фреймворка. Некоторые из этих ресурсов включают миграции, views и конфиги.

В Laravel 5.5 надо уточнять в деталях, что именно мы хотим опубликовать при помощи этой команды. Если мы запускаем команду php artisan vendor:publish без каких-либо флагов, от нас потребуется выбрать выбрать провайдера или тег, чтобы было проще опубликовать только то, что мы хотим. См. скриншот ниже:

php artisan vendor publish

Мы можем обойти этот шаг, если укажем метку --all или --provider при запуске команды publish:


php artisan vendor:publish --all

Разнообразие front-end пресетов

В Laravel 5.3 и 5.4 у нас по умолчанию были некоторые заготовки Vue и Bootstrap, что упрощало front-end разработку. В новой версии в этот набор добавили React. Впрочем, он не стоит там по умолчанию.

Новая команда artisan помогает управлять front-end пресетами. У нас будет только та заготовка, которая нам нужна для того пресета, с которым мы хотим работать. Но не всех устраивают дефолтные пресеты, Vue, Bootstrap и React, кому-то может потребоваться что-то еще. Возможно, другой front-end фреймворк. И Laravel уже позаботился об этом:


php artisan preset none

Эта команда удалит все существующие front-end заготовки. Если бы мы захотели использовать React, следующая команда поможет нам с заготовкой:


php artisan preset react

Ниже представлена эта новая команда в действии:

php artisan preset react


Whoops вернулся!

В Laravel 5.5 вернулся Whoops! с новым способом отображения ошибок. Теперь, если при разработке есть ошибка, мы сможем увидеть эту строчку кода в виде скриншота вместе с сообщением об ошибке. На мой взгляд, сообщение об ошибке теперь выглядит лучше, а то, что мы теперь получаем скриншот с ошибочной строчкой кода, позволяет исправлять ошибки ещё проще.

Пример ошибки с Whoops:

Пример ошибки с Whoops

Еще одна крутая фишка в том, что теперь Whoops позволяет открывать указанные файлы напрямую в вашем IDE или редакторе. Эта функция работает только в том случае, если у вас есть локальный доступ к PHP-файлам на той машине, на которые установлен редактор. Чтобы ее настроить, откройте app/Exceptions/Handler.php и добавьте вот этот сниппет:


[...]
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Arr;
use Whoops\Handler\PrettyPageHandler;
[...]
class Handler extends ExceptionHandler
{
[...]
    protected function whoopsHandler()
    {
        return tap(new PrettyPageHandler, function ($handler) {
            $files = new Filesystem;
            $handler->setEditor('sublime');
            $handler->handleUnconditionally(true);
            $handler->setApplicationPaths(
                array_flip(Arr::except(
                    array_flip($files->directories(base_path())), [base_path('vendor')]
                ))
            );
        });
    }
}

app\Exceptions\Handler.php

Этот сниппет отменяет метод whoopsHandler() основного класса при помощи строчки $handler->setEditor('sublime'), благодаря которой ссылка открывается в Sublime Text. Если вы используете другой редактор, посмотрите статью на гитхабе со списком всех поддерживаемых редакторов и инструкцией, как добавить свой собственный. Если у вас Mac, не забудьте скачать протокол sublime URL для этой работы.


Метод Report кастомных исключений

В предыдущих версиях если мы хотели настроить кастомные исключения каким-то особым образом, нам приходилось размещать их внутри метода report в файле Handler.php. Например так:


[...]
public function report(Exception $exception)
{
    if ($exception instanceof CustomException) {
        // Do something
    }

    if ($exception instanceof MyOtherException) {
        // Do something
    }

    if ($exception instanceof MyOtherCustomException) {
        // Do something
    }

    return parent::report($exception);
}
[...]

app/Exceptions/Handler.php

Если у нас есть, например, 50 основных исключений, то этот файлик превратится в нечто ужасное. В Laravel 5.5, для того чтобы указать, что происходит в случае кастомного исключения, можно создать report() метод внутри исключения:


[...]
class CustomException extends \Exception
{
    public function report()
    {
        // send email
    }
}

[...]

app/Exceptions/CustomException.php


Генераторы фабрик моделей

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

Чтобы создать фабрику для конкретного класса, запускаем команду:


php artisan make:factory Post

Теперь если мы откроем database/factories, то увидим класс PostFactory:


[...]
$factory->define(App\Post::class, function (Faker $faker) {
    return [
        //
    ];
});

database/factories/PostFactory.php

Я считаю, что это более элегантный подход, поскольку мы разделяем ответственности. В предыдущих версиях Laravel все фабрики размещались внутри одного файла app/factories/ModelFactory.php.


Возврат валидированных данных

Теперь стало возможным получить данные из валидатора и передать их в метод create. В предыдущих версиях Laravel мы создавали новые объекты так:


{
    $this->validate(request(), [
        'title' => 'required',
        'body' => 'required'
    ]);

    // return Post::create(request()->only(['title', 'body'])); or
    return Post::create(request()->all());
}

В Laravel 5.5 теперь можно создавать объекты напрямую из валидированных данных:


public function store()
{
    $post = $this->validate(request(), [
        'title' => 'required',
        'body' => 'required'
    ]);

    return Post::create($post);
}

Также можно вызвать команду validate прямо из request’а:


public function store()
{
    $post = request()->validate([
        'title' => 'required',
        'body' => 'required'
    ]);

    return Post::create($post);
}

Замечу, впрочем, что нужно соблюдать осторожность, когда вы создаете объекты таким способом, поскольку любой атрибут, который вы оставите вне метода валидации, не будет иметь значения. Чтобы справиться с этой проблемой, мы передаем все атрибуты, которые мы хотим создать внутри метода валидации для данного объекта, даже если их значения не требуют никакой валидации:


$post = request()->validate([
        'title' => 'required',
        'body' => 'required',
        'notRequiredField' => '',
    ]);

return Post::create($post);

Таким образом, это поле автоматически добавляется к разрешенным данным запроса, но оно не ограничивается никакими правилами валидации.


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

В предыдущих версиях Laravel их можно было задать при помощи метода Validator::extend. Но не было централизации. Мы добавляли правило в файл AppServiceProvider, а затем сообщение в файл inside the resources/lang/en/validation.php. В документации Laravel подробно описано, как это делается в версии 5.4.

В Laravel 5.5 у нас есть новая команда artisan, которая определяет кастомную валидацию. Эта команда создает новый класс, реализующий контракт Rule. Создадим новое правило, чтобы посмотреть, что у него внутри:


php artisan make:rule CustomRule

Если заглянуть в app/Rules/CustomRule.php, то мы увидим два метода — метод passes и метод message. Метод passes берет 2 параметра, т.е. attribute и value, и возвращает boolean. Если вы запутались, $attribute — это поле, которое нужно валидировать, а $value — это реальное значение, которое передается атрибуту.

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


{
    [...]
    public function passes($attribute, $value)
    {
        return $value !== 'unwantedname';
    }

    public function message()
    {
        return 'You cannot use that as your username';
    }
    [...]
}

app/Rules/CustomRule.php

Затем мы используем новое правило, чтобы валидировать атрибут username:


use App\Rules\CustomRule;

request()->validate([
    'username' => [
        'required',
        new CustomRule()
    ],
    'anotherfield' => 'required|min:5'
]);

app/Rules/CustomRule.php

Как определяется кастомная валидация в новой версии Laravel, подробно описано в статье Taylor Otwell.


В коллекции добавлены DD и Dump

Теперь в коллекции включены как метод dump(), так и dd(). В предыдущих версиях Laravel, когда мы отлаживали коллекции, мы назначали переменную коллекции, а потом делали dump, поскольку коллекция изменялась. В Laravel 5.5 так больше делать не придется, поскольку мы теперь можем вызвать команду dd() или dump() прямо из коллекции, что позволяет проводить отладку намного проще.

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


$posts = Post::all();

 $posts
    ->dump()
    ->sorBy('title')
    ->dump()
    ->pluck('title')
    ->dump();

На выходе получаем:


Collection {#284 ▼
    #items: array:3 [▼
        0 => Post {#285 }
        1 => Post {#286 }
        2 => Post {#287 }
    ]
}

Collection {#272 ▼
    #items: array:3 [▼
        0 => Post {#285 }
        2 => Post {#287 }
        1 => Post {#286 }
    ]
}

Collection {#268 ▼
    #items: array:3 [▼
        0 => "Aida Bosco"
        1 => "Madge Leuschke"
        2 => "Miss Bulah Armstrong Jr."
    ]
}

Так легче инспектировать содержание коллекции на каждом шаге. Впрочем. Замечу, что между командами dump() и dd() есть разница. dump() выдает результат на данный момент, а затем продолжает работу, тогда как dd() сразу останавливает процесс и делает dump результатов (dd означает dump and die, сбросить и умереть). Если бы мы вызывали dd() из коллекции на каждом шаге, то мы бы только получили результат в самой первой точке, когда мы вызвали dd() из коллекции. Взгляните:
366666


$posts = Post::all();

 $posts
    ->dump()
    ->sorBy('title')
    ->dd()
    ->pluck('title')
    ->dump();

На выходе получим другое:


Collection {#284 ▼
    #items: array:3 [▼
        0 => Post {#285 }
        1 => Post {#286 }
        2 => Post {#287 }
    ]
}

array:3 [▼
    0 => Post {#285 }
    2 => Post {#287 }
    1 => Post {#286 }
]

Касты в промежуточных таблицах отношений “многие-ко-многим”

Обычно бывает можно объявить свойство casts Модели, которое определяет, как атрибут должен быть сохранен и прочитан. Предположим, у нас есть модель Post, и мы хотим, чтобы одно из полей было сериализовано в JSON при чтении и записи. Следующий сниппет кода нам поможет в этом:


class Post extends Model
{
    [...]
    protected $casts = [
        'somefield' => 'array',
    ];
    [...]
}

Можно было уже кастовать кастомные пивоты в отношения “многие-ко-многим” в версии 5.4, но данные можно было только читать. Если бы мы захотели провести операции записи с данными, нам для начала пришлось бы вручную кастовать значения атрибутов и только потом сохраняться. Теперь так больше делать не надо, поскольку свойство casts в классах Eloquent\Model и Eloquent\Relations\Pivot будет вести себя одинаково, что позволяет использовать методы attach, sync и save в моделях пивотов.


Кастомные директивы Blade::if()

Длинный повторяющийся код проверок в шаблонах blade может сделать их некрасивыми. Хорошая новость в том, что теперь стало возможным извлекать повторяющийся код проверок из шаблонов, что делает их более чистыми и читабельными. Проверки вроде таких:


@if (auth()->check() && auth()->user()->isSubscribed())
    

Subscribed

@else

Not Subscribed

@endif

Можно заменить на:


@subscribed
    

Subscribed

@else

Not Subscribed

@endsubscribed

Логика создания кастомной директивы blade добавляется в метод boot класса AppServiceProvider:


[...]
use Illuminate\Support\Facades\Blade;

class AppServiceProvider extends ServiceProvider
{
    [...]
    public function boot()
    {
        Blade::if('subscribed', function () {
            return auth()->check() && auth()->user()->isSubscribed();
        });
    }
    [...]
}

app/Providers/AppServiceProvider.php

Для некоторых проверок может потребоваться передать какой-то метод аргументу. В таком случае мы передаем аргумент в замыкание, когда речь идет о кастомной директиве blade.


@if (auth()->check() && auth()->user()->isFollowing($user->id))

Если использовать такое условие в качестве примера, то видно, что надо передать $user->id методу isFollowing(). Чтобы создать кастомную директиву blade, которая принимает $user->id как аргумент, делаем следующее:


Blade::if('following', function (User $user) {
    return auth()->check() && auth()->user()->isFollowing($user->id)
});

Затем, чтобы использовать эту новую директиву в наших шаблонах:


@following($user)
    

Following

@else

Not Following

@endfollowing

Авторегистрация новых команд artisan в Kernel

Обычно мы создаем новые команды artisan при помощи команды php artisan make:command command-name. После этого мы назначаем ключ внутри класса с командой, заходим в Kernel и вручную регистрируем команду.

Больше не обязательно регистрировать новые команды в Kernel. У нас теперь есть внутри файла app/Console/kernel.php новый метод, который отслеживает директорию command и превращает все пути файлов в namespaced пути:


[...]
protected function commands()
{
    $this->load(__DIR__.'Commands');

    require base_path('routes/console.php');
}
[...]

Предположим, что мы вызвали команду, которая еще не зарегистрирована в ядре. Метод commands() автоматически ее подключит.


Новые методы маршрутов

Это не самая крутая новая функция, но все же стоит упомянуть, что теперь у нас есть два дополнительных метода маршрутов:


Route::view('/welcome', 'welcome');
Route::redirect('home', 'dashboard');

Первый связывает welcome view с путем /welcome, а второй перенаправляет запросы /home в /dashboard.


Представляем Laravel Horizon

Это новый пакет Laravel, который предоставляет панель и управляемую кодом систему конфигурации для очередей Laravel Redis:

laravel horizon

Horizon в реальном времени показывает нагрузки очередей, недавние задачи, проваленные задачи, попытки перезапуска задач, пропускную способность и рантайм метрики и количество процессов.

Среди функций Horizon есть следующие:


  • Высокоуровневая аналитика для задач — такие показатели, как количество задач в минуту и задачи за прошедший час
  • Аналитика, специфичная для конкретных задач и очередей.
  • Тэги и мониторинг — можно добавлять тэги задачам, а также мониторить конкретные тэги.
  • Недавние задачи — можно получить информацию о самых последних задачах.
  • Стратегии балансировки очередей — Horizon может автоматически распределять процессы queue worker’а по всем очередям в зависимости от их загрузки.

Taylor Otwell в своей статье подробно рассматривает, как настроить Horizon и все функции, которые в него входят.


Новый трейт миграции баз данных

Это трейт RefreshDatabase. Кто-то может удивиться, зачем он вообще понадобился, но у причин, которые стоят за ним, есть смысл. Изначально у нас были трейты DatabaseMigrations и DatabaseTransactions.

Использование трейта DatabaseMigrations в тестах помогает убедиться, что миграции проводятся до и после каждого теста, а трейт DatabaseTransactions позволяет быть уверенным, что база данных восстанавливается в исходное состояние после каждого теста.

Трейт RefreshDatabase объединяет эти две функции, т.к. единожды мигрирует базу данных в начале тестов, а затем оборачивает каждый тест после этого в транзакции. Преимущество в том, что нам не надо повторно мигрировать базу данных для каждого теста, а это значит, что тесты будут проходить быстрее.


Введение

Пакеты (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() уже будет содержать одно действие:

PHP

$this->package('vendor/package');

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

По умолчанию после регистрации пакета его ресурсы будут доступны через часть package из пары vendor/package. Однако, вы можете передать второй аргумент в метод PHPpackage(), чтобы переопределить это поведение. Например:

PHP

// Передача пользовательского пространства имён (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

добавлено в 4.1 ()

Если вы изменили расположение ресурсов вашего пакета, таких как файлы конфигурации или представления, вы должны передать третий аргумент в метод PHPpackage(), который указывает на местоположение ваших ресурсов:

PHP

$this->package('vendor/package'null'/path/to/resources');

Отложенные поставщики

Если вы создаёте поставщик услуг, который не регистрирует какие-либо ресурсы, такие как настройки или представления, вы можете сделать его «отложенным». Отложенный поставщик услуг загружается и регистрируется только тогда, когда одна из услуг, которые он предоставляет, на самом деле необходима IoC-контейнеру приложения. Если ни одна из услуг провайдера не требуется для прохождения данного запроса, поставщик вообще не загружается.

Чтобы отложить выполнение вашего поставщика услуг, установите его свойство defer в значение true:

PHP

protected $defer true;

Затем вам надо переопределить метод PHPprovides() из базового класса Illuminate\Support\ServiceProvider и возвратить массив всех привязок, которые ваш провайдер добавляет в IoC-контейнер. Например, если ваш провайдер регистрирует package.service и package.another-service в IoC-контейнере, то ваш метод PHPprovides() должен выглядеть следующим образом:

PHP

public function provides()
{
  return array(
'package.service''package.another-service');
}

Отложенные поставщики

Если вы создаёте поставщик услуг, который не регистрирует какие-либо ресурсы, такие как настройки или представления, вы можете сделать его «отложенным». Отложенный поставщик услуг загружается и регистрируется только тогда, когда одна из услуг, которые он предоставляет, на самом деле необходима IoC-контейнеру приложения. Если ни одна из услуг провайдера не требуется для прохождения данного запроса, поставщик вообще не загружается.

Чтобы отложить выполнение вашего поставщика услуг, установите его свойство defer в значение true:

PHP

protected $defer true;

Затем вам надо переопределить метод PHPprovides() из базового класса Illuminate\Support\ServiceProvider и возвратить массив всех привязок, которые ваш провайдер добавляет в IoC-контейнер. Например, если ваш провайдер регистрирует package.service и package.another-service в IoC-контейнере, то ваш метод PHPprovides() должен выглядеть следующим образом:

PHP

public function provides()
{
  return array(
'package.service''package.another-service');
}

Соглашения

При использовании ресурсов из пакета, таких как настройки или шаблоны, то для отделения имени пакета обычно используют двойное двоеточие (::).

Загрузка шаблона из пакета

PHP

return View::make('package::view.name');

Чтение параметров настройки в пакете

PHP

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() вашего поставщика услуг.

Подключение файла с маршрутами из поставщика услуг

PHP

public function boot()
{
  
$this->package('vendor/package');

  include 

__DIR__.'/../../routes.php';
}

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

Настройки пакетов

Чтение настроек пакета

Некоторые пакеты могут требовать файлов настройки. Эти файлы должны быть определены аналогично файлам настроек обычного приложения. И затем, при использовании стандартной команды для регистрации ресурсов пакета PHP$this->package(), они будут доступны через обычный синтаксис с двойным равно (::) :

PHP

Config::get('package::file.option');

Чтение параметров из единственного файла настроек

Однако если ваш пакет содержит всего один файл с настройками, вы можете назвать его config.php. Когда это сделано, то его параметры становятся доступными напрямую, без указания имени файла:

PHP

Config::get('package::option');

Ручная регистрация пространства имён ресурсов

Иногда вам может быть нужно зарегистрировать ресурсы пакета вне обычного вызова PHP$this->package(). Обычно это требуется, если ресурс расположен не в стандартном месте. Для регистрации ресурса вручную вы можете использовать методы PHPaddNamespace() классов PHPView, PHPLang и PHPConfig:

PHP

View::addNamespace('package'__DIR__.'/path/to/views');

Как только пространство имён было зарегистрировано, вы можете использовать его имя и двойное двоеточие для получения доступа к ресурсам:

PHP

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

добавлено в 4.1 ()

Представления пакетов

Когда вы используете пакет в вашем приложении, вам может захотеться настроить его представления. Вы легко можете экспортировать представления пакета в вашу папку app/views с помощью Artisan-команды shview:publish:

PHP

php artisan view:publish vendor/package

Эта команда переместит представления пакета в папку app/views/packages. Если эта папка не существует, она будет создана при запуске команды. После того, как представления будут опубликованы, вы можете настроить их на свой вкус! Экспортированные представления автоматически получат приоритет над собственными файлами представлений пакета.

Представления пакетов

Когда вы используете пакет в вашем приложении, вам может захотеться настроить его представления. Вы легко можете экспортировать представления пакета в вашу папку app/views с помощью Artisan-команды shview:publish:

PHP

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. Соблюдение этого соглашения о путях позволит вам использовать их в коде шаблонов вашего пакета.

Введение

Пакеты (packages) - основной способ добавления нового функционала в Laravel. Пакеты могут быть всем, чем угодно - от классов для удобной работы с датами типа Carbon до целых библиотек BDD-тестирования наподобие Behat.

Конечно, всё это разные типы пакетов. Некоторые пакеты самостоятельны, что позволяет им работать в составе любого фреймворка, а не только Laravel. Примерами таких отдельных пакетов являются Carbon и Behat. Любой из них может быть использован в Laravel после простого указания его в файле composer.json.

С другой стороны, некоторые пакеты разработаны специально для использования в Laravel. Они могли содержать роуты, контроллеры, шаблоны, настройки и миграции. Так как для разработки самостоятельных пакетов нет особенных правил, этот раздел документации в основном посвящён разработке именно пакетов для Laravel.

Все пакеты Laravel распространяются через Packagist и Composer, поэтому нужно изучить эти прекрасные средства распространения кода для PHP.

Файлы шаблонов (views)

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

Шаблоны

К шаблонам пакета можно обращаться через так называемую неймспейс-конструкцию :::

return view('package::view.name');

Вам нужно зарегистрить неймспейс шаблонов, указав, где находится папка шаблонов пакета. Делается это в методе boot() сервис-провайдера. Например, так регистрируется неймспейс courier

public function boot()
{
	$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}

Теперь вы можете использовать в контроллере или роуте шаблон пакета таким образом:

return view('courier::view.name');

Когда вы регистрируете папку в loadViewsFrom, Laravel на самом деле регистрирует две папки - одну, которую вы указали и другую - resources/views/vendor. В этой папке лежат шаблоны пакетов, которые пользователи могут изменять под себя. Когда запрашивается шаблон courier::view.name, Laravel сначала пытается загрузить этот шаблон из resources/views/vendor/courier, а затем из папки, заданной в loadViewsFrom.

Публикация шаблонов для изменения

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

public function boot()
{
	$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');

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

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

Чтобы перезаписать имеющися файлы используйте флаг --force:

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

Файлы переводов

Файлы локализации пакета доступны при помощи неймспейс-доступа :::

return trans('package::file.line');

Чтобы зарегистрировать этот неймспейс, воспользуйтесь методом loadTranslationsFrom в boot сервис-провайдера пакета. Например, для неймспейcа courier:

public function boot()
{
	$this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
}

Папка translations пакета должна содержать языковые подпапки, такие как en, es, ru, etc.

Файлы конфигов

Как правило, при установке пакета необходимо, чтобы пользователь мог перенести файлы конфигов к себе в приложение, чтобы иметь возможность менять там настройки. Для организации этой возможности воспользуйтесь методом publishes в boot сервис-провайдера пакета:

$this->publishes([
	__DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
]);

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

Доступ к конфигу осуществляется штатным образом, без неймспейс-нотации:

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

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

$this->mergeConfigFrom(
	__DIR__.'/path/to/config/courier.php', 'courier'
);

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

ВЫ можете разделить файлы, которые можно публиковать в приложение, на группы, и публиковать их раздельно. Например, в пакете есть конфиг и миграции:


$this->publishes([
	__DIR__.'/../config/package.php', config_path('package.php')
], 'config');


$this->publishes([
	__DIR__.'/../database/migrations/' => base_path('/database/migrations')
], 'migrations');

Тепрь пользователь может опубликовать у себя, например, только конфиг:

php artisan vendor:publish --provider="Vendor\Providers\PackageServiceProvider" --tag="config"

Введение

Пакеты — основной способ добавления нового функционала в Laravel. Пакеты могут быть всем, чем угодно — от классов для удобной работы с датами наподобие Carbon, до целых библиотек BDD-тестирования наподобие Behat.

Конечно, существуют разные типы пакетов. Некоторые пакеты автономны, что позволяет им работать в составе любого фреймворка, не только Laravel. Примерами таких отдельных пакетов являются и Carbon, и Behat. Любой из них может быть использован в Laravel с помощью простого указания их в файле composer.json.

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

Заметка о фасадах

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

Сервис-провайдеры

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

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

Ресурсы

Настройка

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


public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
    ]);
}

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

$value = config('courier.option');
Вы не должны задавать функции Closures в своем конфиге. Их нельзя правильно сериализировать, когда пользователи выполняют Artisan-команду config:cache.

Настройки пакета по умолчанию

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


public function register()
{
    $this->mergeConfigFrom(
        __DIR__.'/path/to/config/courier.php', 'courier'
    );
}
Этот метод объединяет только первый уровень массива настройки. Если ваши пользователи частично определяют многомерный массив настройки, отсутствующие параметры не будут объединены.

Роуты

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


public function boot()
{
    $this->loadRoutesFrom(__DIR__.'/routes.php');
}

Миграции

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


public function boot()
{
    $this->loadMigrationsFrom(__DIR__.'/path/to/migrations');
}

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

Переводы

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


public function boot()
{
    $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
}

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

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

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

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


public function boot()
{
    $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');

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

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

Шаблоны

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


public function boot()
{
    $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}

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

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

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

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

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

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


public function boot()
{
    $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');

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

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

Команды

Можно использовать метод commands, чтобы зарегистрировать Artisan-команды вашего пакета в Laravel. Данный метод ожидает массив команд имен класса. Как только команды были зарегистрированы, вы можете выполнить их, используя Artisan CLI:


public function boot()
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            FooCommand::class,
            BarCommand::class,
        ]);
    }
}

Общие ресурсы

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


public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/assets' => public_path('vendor/courier'),
    ], 'public');
}

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

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

Введение

Пакеты (packages) — основной способ добавления нового функционала в Laravel. Пакеты могут быть всем, чем угодно — от классов для удобной работы с датами наподобие Carbon, до целых библиотек BDD-тестирования наподобие Behat.

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

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

Все пакеты Laravel распространяются через Packagist и Composer, поэтому нужно изучить эти прекрасные средства распространения пакетов для PHP.

+ 5.3

добавлено в 5.3 ()

Замечание о фасадах

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

Сервис-провайдеры

Сервис-провайдеры — связующие элементы между вашим пакетом и Laravel. Они содержит привязки сервис-контейнера, а также инструкции о том, где хранятся настройки пакета, его представления и языковые файлы.

Сервис-провайдер наследует класс Illuminate\Support\ServiceProvider и содержит два метода: PHPregister() и PHPboot(). Базовый класс ServiceProvider находится в пакете Composer illuminate/support, который вы должны добавить в зависимости своего пакета. Подробнее о структуре и задачах сервис-провайдеров читайте в документации.

Маршруты

+ 5.3

добавлено в 5.3 ()

Чтобы определить маршруты для своего пакета, передайте файл маршрутов в метод PHPloadRoutesFrom() из метода PHPboot() сервис-провайдера вашего пакета. В этом файле вы можете использовать фасад Illuminate\Support\Facades\Route для регистрации маршрутов, точно так же, как в обычном приложении Laravel:

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  
$this->loadRoutesFrom(__DIR__.'/path/to/routes.php');
}

+ 5.2 5.1

добавлено в 5.2 () 5.1 ()

Чтобы определить маршруты для своего пакета, просто затребуйте (PHPrequire) файл маршрутов в методе PHPboot() вашего сервис-провайдера. В этом файле вы можете использовать фасад Route для регистрации маршрутов, точно так же, как в обычном приложении Laravel:

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  if (! 
$this->app->routesAreCached()) {
    require 
__DIR__.'/../../routes.php';
  }
}

+ 5.0

добавлено в 5.0 ()

Чтобы загрузить файл маршрутов для вашего пакета, просто подключите его (include) в методе PHPboot() вашего сервис-провайдера.

PHP

public function boot()
{
  include 
__DIR__.'/../../routes.php';
}

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

Ресурсы

Настройки

В типичном случае вам потребуется опубликовать файл настроек вашего пакета в папку config самого приложения. Это позволит пользователям вашего пакета легко изменять настройки по умолчанию. Чтобы позволить вашим файлам быть опубликованными, вызовите метод PHPpublishes() из метода PHPboot() вашего сервис-провайдера:

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  
$this->publishes([
    
__DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
  ]);
}

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

PHP

$value config('courier.option');

Настройки пакета по умолчанию

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

PHP

/**
 * Регистрация привязок в контейнере.
 *
 * @return void
 */
public function register()
{
  
$this->mergeConfigFrom(
    
__DIR__.'/path/to/config/courier.php''courier'
  
);
}

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

+ 5.3

добавлено в 5.3 ()

Миграции

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

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  
$this->loadMigrationsFrom(__DIR__.'/path/to/migrations');
}

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

Переводы

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

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  
$this->loadTranslationsFrom(__DIR__.'/path/to/translations''courier');
}

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

PHP

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

Помните, что в вашей папке с переводами должны быть подпапки для каждого языка, такие как en, es, ru и т.д.

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

Для публикации переводов вашего пакета в папку resources/lang/vendor приложения, используйте метод сервис-провайдера PHPpublishes(). Этот метод принимает массив путей к переводам пакета и предполагаемые места для их публикации. Например, для публикации языковых файлов пакета courier сделайте так:

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  
$this->loadTranslationsFrom(__DIR__.'/path/to/translations''courier');$this->publishes([
    
__DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'),
    
//для версии 5.1 и ранее:
    //__DIR__.'/path/to/translations' => base_path('resources/lang/vendor/courier'),
  
]);
}

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

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

Для регистрации представлений вашего пакета в Laravel, вам надо указать Laravel, где они расположены. Вы можете сделать это методом PHPloadViewsFrom(). Этот метод принимает два аргумента: путь к шаблонам ваших представлений и название пакета. Например, если ваш пакет называется courier, вам надо добавить в метод PHPboot() своего сервис-провайдера следующее:

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  
$this->loadViewsFrom(__DIR__.'/path/to/views''courier');
}

На представления пакета ссылаются, используя синтаксис PHPpackage::view. Поэтому, когда путь вашего представления зарегистрирован в сервис-провайдере, вы можете загрузить представление admin из пакета courier таким образом:

PHP

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

Переопределение представлений пакета

Когда вы используете метод PHPloadViewsFrom(), на самом деле Laravel регистрирует два расположения для ваших представлений: в папке приложения resources/views/vendor и в указанной вами папке. Поэтому в нашем примере с courier Laravel сначала проверит, предоставил ли разработчик свою версию представления в PHPresources/views/vendor/courier. Затем, если представление не было изменено, Laravel будет искать в вызове PHPloadViewsFrom() указанную вами папку представлений пакета. Это упрощает редактирование или замену представлений вашего пакета для тех, кто им будет пользоваться.

Публикация представлений

Для публикации представлений вашего пакета в папку resources/views/vendor используйте метод PHPpublishes() в методе PHPboot() вашего сервис-провайдера. Метод PHPpublishes() принимает массив путей к представлениям пакета и предполагаемые места для их публикации.

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  
$this->loadViewsFrom(__DIR__.'/path/to/views''courier');$this->publishes([
    
__DIR__.'/path/to/views' => resource_path('views/vendor/courier'),
    
//для версии 5.1 и ранее:
    //__DIR__.'/path/to/views' => base_path('resources/views/vendor/courier'),
  
]);
}

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

+ 5.3

добавлено в 5.3 ()

Команды

Для регистрации в Laravel Artisan-команд вашего пакета используйте метод PHPcommands(). Этот метод принимает массив имён классов команд. После регистрации команд вы можете выполнять их через консоль Artisan:

PHP

/**
 * Начальная загрузка сервисов приложения.
 *
 * @return void
 */
public function boot()
{
  if (
$this->app->runningInConsole()) {
    
$this->commands([
      
FooCommand::class,
      
BarCommand::class,
    ]);
  }
}

Команды

Для регистрации в Laravel Artisan-команд вашего пакета используйте метод PHPcommands(). Этот метод принимает массив имён классов команд. После регистрации команд вы можете выполнять их через консоль Artisan:

PHP

/**
 * Начальная загрузка сервисов приложения.
 *
 * @return void
 */
public function boot()
{
  if (
$this->app->runningInConsole()) {
    
$this->commands([
      
FooCommand::class,
      
BarCommand::class,
    ]);
  }
}

Общие ресурсы

Ваш пакет может иметь ресурсы, такие как JavaScript, CSS и изображения. Для публикации этих ресурсов в папку приложения public используйте метод PHPpublishes() в методе PHPboot() вашего сервис-провайдера. В этом примере мы также добавим для ресурсов групповой тег «public», который можно использовать для публикации групп связанных ресурсов:

PHP

/**
 * Выполнение после-регистрационной загрузки сервисов.
 *
 * @return void
 */
public function boot()
{
  
$this->publishes([
    
__DIR__.'/path/to/assets' => public_path('vendor/courier'),
  ], 
'public');
}

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

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

+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

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