Прежде, чем мы начнем, создайте пустую папку для вашего нового пакета - название может быть абсолютно любым и не играет значения. Затем зайдите в эту папку через терминал и выполните команду composer init. Запустится скрипт генерации файла composer.json.

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

Package name (<vendor>/<name>) [***/***]: voerro/simple-package (имя пакета)
Description []: A dead simple Laravel package (описание пакета)
Author [***, n to skip]: Alexander Zavyalov <alexander@email.com> (автор пакета)
Minimum Stability []: stable (введите "stable")
Package Type (e.g. library, project, metapackage, composer-plugin) []: library (тип пакета, введите "library")
License []: MIT (тип лицензии, мы будем использовать MIT в нашем примере)
Would you like to define your dependencies (require) interactively [yes]? n (введите "n" - мы отредактируем этот блок позже вручную)
Would you like to define your dev dependencies (require-dev) interactively [yes]? n (введите "n" - мы отредактируем этот блок позже вручную)
Do you confirm generation [yes]? yes (подтверждение генерации файла, введите "yes")

Minimum Stability []: stable означает, что когда кто-нибудь захочет установить ваш пакет, им будет установлена последняя стабильная версия пакета (не dev версия). Если доступных стабильных версий у пакета нет, пользователю будет показана ошибка.

Теперь в нашей новой папке есть один единственный файл - composer.json. Давайте откроем этот файл. Кстати, можете заодно инициализировать новый git репозиторий в папке.

{
    "name": "voerro/simple-package",
    "description": "A dead simple Laravel package",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Alexander Zavyalov",
            "email": "alexander@email.com"
        }
    ],
    "minimum-stability": "stable",
    "require": {}
}

Давайте добавим необходимые зависимости для нашего проекта вручную (мы пропустили этот шаг ранее). Сначала добавим php. Минимальная версия PHP, поддерживаемая Laravel 5.5 - версия 7.0. Так же для разработки нам понадобятся phpunit/phpunit и orchestra/testbench. Вот как должен выглядеть блок "require" после всех дополнений:

"require": {
    "php": ">=7.0"
},
"require-dev": {
    "phpunit/phpunit": "^6.5",
    "orchestra/testbench": "^3.5"
}

orchestra/testbench позволит нам тестировать наш пакет так, как если бы мы вели разработку внутри реального проекта Laravel. Ниже, под списком зависимостей, нам нужно указать псевдонимы для автозагрузки файлов классов по стандарту PSR-4.

"autoload": {
    "psr-4": {
        "Voerro\\SimplePackage\\": "src/"
    }
},
"autoload-dev": {
    "psr-4": {
        "Voerro\\SimplePackage\\Test\\": "tests/"
    }
},

В качестве псевдонимов может быть использовано что угодно, но лучше выбирать их исходя из имени пакета. Наши 2 псевдонима указывают на папки src и test соответственно. Создайте обе эти папки в корне. Наконец, нам нужно добавить блок extra, в котором мы укажем информацию, необходимую для авто-подключения пакетов в Laravel начиная с версии 5.5. SimplePackage в блоке "aliases" - это то, как мы назовем главный класс нашего пакета.

"extra": {
    "laravel": {
        "providers": [
            "Voerro\\SimplePackage\\SimplePackageServiceProvider"
        ],
        "aliases": {
            "SimplePackage": "Voerro\\SimplePackage\\SimplePackageFacade"
        }
    }
}

Теперь создайте 3 файла в папке src (SimplePackageServiceProvider.php, SimplePackageFacade.php, and SimplePackage.php) со следующим содержимым.

SimplePackageFacade.php

<?php

namespace Voerro\SimplePackage;

use Illuminate\Support\Facades\Facade;

class SimplePackageFacade extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'simple-package';
    }
}

SimplePackageServiceProvider.php

<?php

namespace Voerro\SimplePackage;

use Illuminate\Support\ServiceProvider;

class SimplePackageServiceProvider extends ServiceProvider
{
    /**
     * Регистрирует сервисы приложения.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(SimplePackage::class, function () {
            return new SimplePackage();
        });

        $this->app->alias(SimplePackage::class, 'simple-package');
    }
}

SimplePackage.php

<?php

namespace Voerro\SimplePackage;

class SimplePackage
{
    //
}

В файле SimplePackage.php будет основной код пакета.

Сервис-провайдер SimplePackageServiceProvider.php служит связкой между нашим пакетом и Laravel.

Фасад SimplePackageFacade.php предоставляет "статический" интерфейс для главного класса нашего пакета.

Как вы, наверное, заметили, фасад и сервис-провайдер импортируют два класса из пространства имен Illuminate\Support. Нам нужно добавить соответствующий пакет Laravel в раздел require файла composer.json. Не забывайте добавлять туда все сторонние пакеты, которые будут использоваться в вашем собственном.

"require": {
    "php": ">=7.0",
    "illuminate/support": ">=5.5"
},
"require-dev": {
    "phpunit/phpunit": "^6.5",
    "orchestra/testbench": "^3.5"
},

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

<?php

namespace Voerro\SimplePackage;

class SimplePackage
{
    public static function add($a, $b) {
        return $a + $b;
    }
}

Теперь перейдем к тестированию. Другого способа убедиться, что все работает правильно, находясь вне проекта Laravel просто нет - мы не можем запустить наш пакет стационарно каким-либо образом. Создайте файл TestCase.php в папке tests. Это будет наш родительский тестовый класс, который наследует другой класс из пакета orchestra/testbench, который упомянался ранее.

<?php

namespace Voerro\SimplePackage\Test;

use Voerro\SimplePackage\SimplePackageFacade;
use Voerro\SimplePackage\SimplePackageServiceProvider;
use Orchestra\Testbench\TestCase as OrchestraTestCase;

class TestCase extends OrchestraTestCase
{
    /**
     * Загружает сервис-провайдер пакета
     *
     * @param  \Illuminate\Foundation\Application $app
     * @return Voerro\SimplePackage\SimplePackageServiceProvider
     */
    protected function getPackageProviders($app)
    {
        return [SimplePackageServiceProvider::class];
    }

    /**
     * Возвращает псевдоним главного класса пакета
     *
     * @param  \Illuminate\Foundation\Application $app
     * @return array
     */
    protected function getPackageAliases($app)
    {
        return [
            'SimplePackage' => SimplePackageFacade::class,
        ];
    }
}

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

<?php

namespace Voerro\SimplePackage\Test;

use Voerro\SimplePackage\SimplePackage;

class SimplePackageTest extends TestCase
{
    public function testAddition()
    {
        $result = SimplePackage::add(17, 3);

        $this->assertEquals(20, $result);
    }
}

Наконец, создайте файл phpunit.xml в корне пакета со следующим содержимым:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
         backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         verbose="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Test Suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory suffix=".php">src/</directory>
        </whitelist>
    </filter>
</phpunit>

Код готов. Выполните команду composer install в терминале, чтобы скачались все зависимости для нашего пакета. Далее выполните phpunit (или vendor/bin/phpunit, если PHPUnit у вас не установлен глобально) - убедитесь, что наш тест проходит успешно. Мы сделали шаблон простейшего пакета Laravel, можете использовать его для своих собственных разработок. Но не торопитесь - в одной из следующих частей данного урока мы рассмотрим как делать более продвинутые пакеты.