Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Junior: питання на співбесіді з теми «Розробка пакетів»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

2 питання

Laravel-пакет - це звичайний Composer-пакет, який інтегрується з фреймворком через сервіс-провайдер. Мінімальна структура:

acme/laravel-invoices/
├── composer.json
├── config/invoices.php
├── src/
│   ├── InvoicesServiceProvider.php
│   ├── InvoiceGenerator.php
│   └── Facades/Invoices.php
├── database/migrations/
├── resources/views/
└── tests/

Сервіс-провайдер - точка входу: реєструє класи в контейнері (register) і підключає конфігурацію, маршрути, представлення, міграції, команди (boot).

class InvoicesServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->mergeConfigFrom(__DIR__.'/../config/invoices.php', 'invoices');
        $this->app->singleton(InvoiceGenerator::class);
    }

    public function boot(): void
    {
        $this->loadViewsFrom(__DIR__.'/../resources/views', 'invoices');
    }
}

Автоматичне виявлення (package discovery): провайдер і фасади описуються в composer.json пакета:

{
    "name": "acme/laravel-invoices",
    "autoload": {
        "psr-4": { "Acme\\Invoices\\": "src/" }
    },
    "extra": {
        "laravel": {
            "providers": ["Acme\\Invoices\\InvoicesServiceProvider"],
            "aliases": { "Invoices": "Acme\\Invoices\\Facades\\Invoices" }
        }
    }
}

Після composer require скрипт php artisan package:discover (Laravel запускає його в post-autoload-dump) читає секції extra.laravel усіх встановлених пакетів і записує список у bootstrap/cache/packages.php. Користувачу не треба нічого додавати в bootstrap/providers.php.

Як вимкнути виявлення - у composer.json застосунку:

"extra": {
    "laravel": {
        "dont-discover": ["barryvdh/laravel-debugbar"]
    }
}

Наприклад, щоб підключати налагоджувальний пакет лише в локальному середовищі через власний провайдер.

Якщо пакет «не підхопився»: перевірити bootstrap/cache/packages.php, виконати php artisan package:discover і переконатися, що composer install не запускався з --no-scripts (тоді discover не виконується).

Залежності пакета: вимагати лише ті компоненти, які використовуються (illuminate/support, illuminate/database), а не весь laravel/framework - так пакет легше встановити й у застосунки на компонентах Laravel.

Докладніше в документації: Пакети: виявлення пакетів

Коли пакет пишеться для конкретного застосунку (або виділяється з нього), незручно щоразу публікувати версію, щоб перевірити зміну. Path-репозиторій підключає пакет з локального каталогу.

~/code/
├── shop/                    # застосунок
└── packages/
    └── laravel-invoices/    # пакет

У composer.json застосунку:

{
    "repositories": [
        {
            "type": "path",
            "url": "../packages/laravel-invoices",
            "options": { "symlink": true }
        }
    ],
    "require": {
        "acme/laravel-invoices": "@dev"
    }
}
composer update acme/laravel-invoices

Composer створює символьне посилання vendor/acme/laravel-invoices → ../packages/laravel-invoices. Зміни в коді пакета видно в застосунку одразу, без повторного встановлення.

Що варто знати:

  • версія: @dev бере поточний стан каталогу. Якщо в пакеті є Git-теги чи поле version, можна вимагати й звичайне обмеження (^1.0);
  • автозавантаження: після додавання нових класів у пакет зазвичай достатньо symlink, але при зміні секції autoload у composer.json пакета - composer dump-autoload у застосунку;
  • package discovery спрацьовує як для звичайного пакета;
  • у Docker symlink на каталог поза проєктом не працюватиме, якщо цей каталог не змонтовано в контейнер. Часто пакет тримають усередині репозиторію (packages/ у корені) з "url": "packages/*";
  • symlink: false - копіювання замість посилання: стабільніше для CI чи образів, але зміни потребують composer update.

Не забути перед публікацією:

  • прибрати path-репозиторій з composer.json застосунку (чи тримати його лише локально) і вимагати опубліковану версію;
  • перевірити, що пакет встановлюється «з нуля» без застосунку - тести через Orchestra Testbench саме це й перевіряють.

Альтернатива для приватних пакетів: vcs-репозиторій (Git URL), Private Packagist чи Satis - тоді пакет встановлюється з тегів, як публічний.

Стартовий шаблон: замість ручного створення структури можна взяти spatie/package-skeleton-laravel - там уже налаштовані Testbench, Pest, PHPStan, GitHub Actions і публікація конфігурації.

Докладніше в документації: Пакети: створення пакета