Laravel Ingest від Robin Kopp — пакет ETL (Extract, Transform, Load), керований конфігурацією, який замінює одноразові імпортні скрипти декларативними класами-імпортерами. Він обробляє файли від кількох сотень до десятків мільйонів рядків, пропускаючи їх через PHP Generators і Laravel Queues та зберігаючи постійне споживання пам’яті незалежно від розміру файлу.
# Основні можливості
- Декларативні класи-імпортери з Fluent-білдером
IngestConfig - Автоматичне розв’язання
BelongsToіBelongsToManyвідносин - Стратегії обробки дублікатів:
SKIP,CREATE,UPDATEтаUPDATE_IF_NEWER - Режим dry-run для перевірки імпортів без запису в базу
- Відстеження невдалих рядків з можливістю завантажити їх у CSV
- Аліаси колонок для мапінгу різних назв заголовків на одне поле
- Динамічне визначення моделі на основі даних рядка
- Джерела імпорту: завантаження файлу, диски файлової системи (включно з S3), URL, FTP та SFTP
- Автоматично згенеровані Artisan-команди та REST-ендпоїнти для кожного імпортера
# Визначення імпортера
Після встановлення пакета і виконання міграцій створіть клас-імпортер, що реалізує IngestDefinition і повертає IngestConfig. За конвенцією такі класи розміщують у просторі імен App\Ingest:
namespace App\Ingest;
use App\Models\Product;
use LaravelIngest\Contracts\IngestDefinition;
use LaravelIngest\DTOs\IngestConfig;
use LaravelIngest\Enums\DuplicateStrategy;
use LaravelIngest\Enums\SourceType;
class ProductImporter implements IngestDefinition
{
public function getConfig(): IngestConfig
{
return IngestConfig::for(Product::class)
->fromSource(SourceType::UPLOAD)
->keyedBy('sku')
->onDuplicate(DuplicateStrategy::UPDATE)
->map('Product Name', 'name')
->relate('Category', 'category', Category::class, 'slug')
->validate([
'sku' => 'required|string',
'Product Name' => 'required|string|min:3',
]);
}
}
Зареєструйте імпортер у своєму AppServiceProvider, використовуючи тег пакета:
use LaravelIngest\IngestServiceProvider;
$this->app->tag([ProductImporter::class], IngestServiceProvider::INGEST_DEFINITION_TAG);
# Запуск імпортів
Після реєстрації пакет надає і Artisan-команду, і HTTP-ендпоїнт для кожного імпортера.
Через CLI:
php artisan ingest:run product-importer --file=products.csv
Через API (multipart form upload):
POST /api/v1/ingest/upload/product-importer
Для dry-run додайте прапорець --dry-run до Artisan-команди — файл перевірять, а база не зміниться.
# Моніторинг
Пакет містить декілька Artisan-команд для перевірки запущених або завершених імпортів:
php artisan ingest:list # List registered importers
php artisan ingest:status {id} # Show progress and row statistics
php artisan ingest:cancel {id} # Stop an in-progress import
php artisan ingest:retry {id} # Reprocess only the failed rows
Такі самі REST-ендпоїнти також доступні:
GET /api/v1/ingest— недавні запускиGET /api/v1/ingest/{id}— статус і статистикаGET /api/v1/ingest/{id}/errors/summary— агрегована статистика помилокGET /api/v1/ingest/{id}/failed-rows/download— CSV рядків, що не пройшли
# Події
Пакет диспатчить події впродовж усього життєвого циклу імпорту — IngestRunStarted, ChunkProcessed, RowProcessed, IngestRunCompleted і IngestRunFailed — які можна слухати для сповіщень або кастомних побічних ефектів.
Laravel Ingest доступний на GitHub, а повну документацію — на Laravel Ingest docs.