Розробка кастомного пакета Bagisto
Bagisto будується на концепції Laravel-пакетів: кожна функціональна одиниця системи — це ізольований модуль з власними моделями, контролерами, маршрутами та представленнями. Кастомний пакет дозволяє додати будь-яку логіку без змін vendor-коду та без ломання оновлень ядра.
Структура пакета
packages/
└── MyCompany/
└── Catalog/
├── src/
│ ├── Http/
│ │ ├── Controllers/
│ │ │ └── Admin/CatalogController.php
│ │ └── Requests/
│ ├── Models/
│ │ └── CustomAttribute.php
│ ├── Repositories/
│ │ └── CustomAttributeRepository.php
│ ├── Database/
│ │ ├── Migrations/
│ │ └── Seeders/
│ ├── Resources/
│ │ ├── assets/
│ │ │ ├── js/
│ │ │ └── css/
│ │ └── views/
│ │ └── admin/
│ ├── Config/
│ │ └── menu.php
│ ├── Routes/
│ │ ├── admin.php
│ │ └── shop.php
│ └── Providers/
│ └── CatalogServiceProvider.php
└── composer.json
Реєстрація пакета
composer.json кореневого проекту:
{
"autoload": {
"psr-4": {
"MyCompany\\Catalog\\": "packages/MyCompany/Catalog/src"
}
}
}
composer dump-autoload
ServiceProvider — точка входу пакета:
<?php
namespace MyCompany\Catalog\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Event;
class CatalogServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->mergeConfigFrom(
__DIR__.'/../Config/menu.php', 'menu'
);
}
public function boot(): void
{
$this->loadRoutesFrom(__DIR__.'/../Routes/admin.php');
$this->loadRoutesFrom(__DIR__.'/../Routes/shop.php');
$this->loadMigrationsFrom(__DIR__.'/../Database/Migrations');
$this->loadViewsFrom(__DIR__.'/../Resources/views', 'mycompany-catalog');
$this->loadTranslationsFrom(__DIR__.'/../Resources/lang', 'mycompany-catalog');
$this->publishes([
__DIR__.'/../Resources/assets' => public_path('vendor/mycompany/catalog'),
], 'mycompany-catalog-assets');
// Підписуємося на события ядра
Event::listen(
'catalog.product.create.after',
'MyCompany\Catalog\Listeners\ProductCreatedListener'
);
}
}
Реєстрація в config/app.php:
'providers' => [
// ...
MyCompany\Catalog\Providers\CatalogServiceProvider::class,
],
Репозиторії замість прямих запитів
Bagisto використовує паттерн Repository над Eloquent. Кастомні репозиторії наслідують базовий клас ядра:
<?php
namespace MyCompany\Catalog\Repositories;
use Webkul\Core\Eloquent\Repository;
use MyCompany\Catalog\Models\CustomAttribute;
class CustomAttributeRepository extends Repository
{
public function model(): string
{
return CustomAttribute::class;
}
public function getByProduct(int $productId): \Illuminate\Support\Collection
{
return $this->where('product_id', $productId)
->where('is_active', true)
->orderBy('sort_order')
->get();
}
}
Реєстрація в ServiceProvider:
$this->app->bind(
\MyCompany\Catalog\Repositories\CustomAttributeRepository::class
);
Додання пункту в меню адміністратора
// Config/menu.php
return [
[
'key' => 'mycompany',
'name' => 'MyCompany',
'route' => 'mycompany.catalog.index',
'sort' => 10,
'icon' => 'icon-catalog',
],
[
'key' => 'mycompany.catalog',
'name' => 'Каталог',
'route' => 'mycompany.catalog.index',
'sort' => 1,
'icon' => '',
],
];
Vue-компоненти в пакеті
Bagisto 2.x використовує Vue 3 + Vite. Компоненти пакета реєструються глобально:
// packages/MyCompany/Catalog/src/Resources/assets/js/index.js
import CustomAttributeForm from './components/CustomAttributeForm.vue';
export default {
install(app) {
app.component('custom-attribute-form', CustomAttributeForm);
}
}
Підключення в vite.config.js кореневого проекту через resolve.alias або через публікацію ассетів.
Перехват событий ядра
Bagisto генерує события в ключевих точках — це основний механізм розширення без патчування:
| Событие | Коли спрацьовує |
|---|---|
checkout.order.save.after |
Після створення замовлення |
catalog.product.create.after |
Після створення товара |
customer.registration.after |
Після реєстрації покупця |
sales.invoice.save.after |
Після створення інвойса |
catalog.product.update.after |
Після оновлення товара |
<?php
namespace MyCompany\Catalog\Listeners;
class ProductCreatedListener
{
public function handle($product): void
{
// Відправка в чергу для індексації в Elasticsearch
dispatch(new \MyCompany\Catalog\Jobs\IndexProduct($product->id));
}
}
Тестування пакета
<?php
namespace MyCompany\Catalog\Tests\Unit;
use Tests\TestCase;
use MyCompany\Catalog\Repositories\CustomAttributeRepository;
class CustomAttributeRepositoryTest extends TestCase
{
public function test_returns_active_attributes(): void
{
$repo = app(CustomAttributeRepository::class);
$attrs = $repo->getByProduct(1);
$this->assertInstanceOf(\Illuminate\Support\Collection::class, $attrs);
$this->assertTrue($attrs->every(fn($a) => $a->is_active));
}
}
Терміни розробки
| Тип пакета | Термін |
|---|---|
| Простий (CRUD + меню) | 1-3 дні |
| Інтеграція з зовнішнім API | 3-7 днів |
| Кастомний checkout-flow | 1-2 тижні |
| Повний модуль (marketplace vendor) | 2-4 тижні |
Пакет оформляється з composer.json, тестами та документацією — це важливо при передачі команді або при оновленні Bagisto до наступної мажорної версії.







