Database brick
Коли форма вже валідується, наступний біль — куди зберігати
дані і як еволюціонувати схему без ручного SQL у проді.
addDatabase() на ConceptStack
підключає Illuminate/Eloquent через
extension-database-eloquent:
connection, міграції, seeders, опційно query log і events.
Повертає DatabaseBuilder. Рецепт з MySQL —
База даних.
Stack не читає .env — масив connection передає
Bootstrap (literal + getenv()).
Методи DatabaseBuilder:
| Метод | Параметри | Опис | Залежність |
|---|---|---|---|
setConnection() |
array<string, mixed> $connection |
Illuminate connection (driver, host, database, username, password, …) | — |
setMigrations() |
list<string> $paths |
Абсолютні шляхи до каталогів з migration files | — |
setMigrationsTable() |
string $table |
Таблиця обліку виконаних міграцій | — |
setSeeders() |
list<class-string> $seeders |
Seeder classes для SeederManager | — |
withQueryLogging() |
string $logFilePath, int $maxFiles = 7 |
Opt-in rotating SQL query log | — |
withMasking() |
— | Маскування чутливих полів у query log | addMasking() |
withEmitQueryEvents() |
— | Emit DatabaseQueryExecuted events |
addEvents() |
setConnection()
$stack->addDatabase()
->setConnection([
'driver' => 'mysql',
'host' => getenv('MYSQL_HOST') ?: '127.0.0.1',
'port' => (int) (getenv('MYSQL_PORT') ?: 3306),
'database' => getenv('MYSQL_DATABASE') ?: 'concept_recipes',
'username' => getenv('MYSQL_USER') ?: 'root',
'password' => getenv('MYSQL_PASSWORD') ?: 'root',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
]);
Без connection немає Capsule — інжект
DatabaseInterface у controller не має куди йти.
Масив іде в
extension-database-eloquent
зі стандартними ключами Illuminate. Glue збирає значення сам
(env Docker vs local), Stack їх не шукає у файлах — той самий
принцип «explicit arguments», що й у інших bricks.
setMigrations()
$stack->addDatabase()
->setMigrations([$rootPath . 'database/migrations']);
Абсолютні шляхи до PHP-migration files потрапляють у
MigrationRegistry — Migrator знає, де
шукати файли. Кілька каталогів — коли міграції розкидані по
пакетах/компонентах, а не лише в одному app-корені.
setMigrationsTable()
$stack->addDatabase()
->setMigrationsTable('migrations');
Таблиця обліку виконаних міграцій (Illuminate
DatabaseMigrationRepository). Default —
migrations. Задавай явно, якщо кілька додатків
ділять одну БД і потрібні різні таблиці обліку — інакше
міграції одного додатку «бачать» історію іншого.
setSeeders()
$stack->addDatabase()
->setSeeders([
ContactSubmissionsSeeder::class,
]);
Демо-дані / фікстури: class-string список seeder-ів
(SeederInterface) потрапляє в
SeederManager. Список класів — на Database brick,
не в CLI-командах.
withQueryLogging()
$stack->addDatabase()
->setConnection([ /* … */ ])
->withQueryLogging($rootPath . 'storage/logs/query.log', 7);
Opt-in, коли треба побачити реальний SQL під час розробки
(N+1, зайві запити). RotatingFileHandler усередині
DatabaseEloquentServiceProvider. Без виклику
запити в файл не пишуться — на проді зазвичай не вмикають
постійно. Це окремий sink від app Monolog.
withMasking()
$stack->addMasking()
->setPatterns([ /* … */ ]);
$stack->addDatabase()
->setConnection([ /* … */ ])
->withQueryLogging($rootPath . 'storage/logs/query.log')
->withMasking();
Query log легко просочує паролі й токени в bindings. Opt-in
маскування викликає require(DATABASE, MASKING):
без addMasking() Stack не збереться. Має сенс
лише разом із withQueryLogging() — інакше
маскувати нічого.
withEmitQueryEvents()
$stack->addEvents();
$stack->addDatabase()
->setConnection([ /* … */ ])
->withEmitQueryEvents();
Коли потрібна телеметрія або кастомне логування без файлового
query log: після SQL емітиться
DatabaseQueryExecuted (listeners через Events brick).
require(DATABASE, EVENTS) — потрібен
addEvents().
Що реєструє brick
DatabaseEloquentServiceProvider→DatabaseInterface(Capsule)MigrationRegistry— шляхи зsetMigrations()- Migrator + repository (таблиця з
setMigrationsTable()) - SeederManager — класи з
setSeeders() PaginationConfiguratorServiceProvider— pagination defaults
Controllers/services інжектять DatabaseInterface,
не Capsule напряму — легше підміняти в тестах. Eloquent Model —
опційно в додатку; brick його не вимагає.
Мінімальний фрагмент
$stack->addDatabase()
->setConnection([ /* driver, host, … */ ])
->setMigrations([$rootPath . 'database/migrations'])
->setMigrationsTable('migrations')
->setSeeders([ContactSubmissionsSeeder::class]);
Рецепт — 6. База даних. Каталог bricks — Bricks і addX(). Extension — Database.