<? phpukraine ДОКУМЕНТАЦІЯ
Пошук по платформі
Документація українською

Переклад офіційної документації українською. Кожен розділ показує стан готовності: недоперекладене позначене відкрито, а не приховане.

ВЕРСІЯ
АКТУАЛЬНА Актуальний реліз. Переклад наздоганяє оригінал — розділи з низьким відсотком позначені у змісті.
DOCTRINE · ПЕРЕКЛАДЕНО оновлено 5 вересня 2026

DBAL — Symfony

Ця стаття про Doctrine DBAL. Зазвичай ви працюватимете з вищим рівнем — шаром Doctrine ORM, який використовує DBAL «під капотом», щоб фактично спілкуватися з базою даних. Докладніше про Doctrine ORM читайте в розділі «Doctrine».

Рівень абстракції бази даних (Database Abstraction Layer, DBAL) від Doctrine — це шар абстракції, який лежить поверх PDO та пропонує інтуїтивний і гнучкий API для спілкування з найпопулярнішими реляційними базами даних. Бібліотека DBAL дозволяє писати запити незалежно від ваших моделей ORM, наприклад, для побудови звітів або прямих маніпуляцій із даними.

Порада: прочитайте офіційну документацію DBAL від Doctrine, щоб дізнатися всі подробиці та можливості бібліотеки Doctrine DBAL.

Спершу встановіть Symfony pack orm від Doctrine:

$ composer require symfony/orm-pack

Потім налаштуйте змінну середовища DATABASE_URL у .env:

# .env (або перевизначте DATABASE_URL у .env.local, щоб не комітити свої зміни)

# змініть цей рядок!
DATABASE_URL="mysql://db_user:[email protected]:3306/db_name?serverVersion=8.0.37"

Інші речі можна налаштувати у config/packages/doctrine.yaml — див. довідник конфігурації Doctrine DBAL. Приберіть ключ orm у цьому файлі, якщо ви не хочете використовувати Doctrine ORM.

Далі ви можете дістатися до зʼєднання Doctrine DBAL через автопідключення обʼєкта Connection:

// src/Controller/UserController.php
namespace App\Controller;

use Doctrine\DBAL\Connection;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class UserController extends AbstractController
{
    public function index(Connection $connection): Response
    {
        $users = $connection->fetchAllAssociative('SELECT * FROM users');

        // ...
    }
}

Це передасть вам сервіс database_connection.

Використання зʼєднань Primary/Replica (репліки для читання)

Коли ваш застосунок використовує кластер бази даних із репліками для читання, ви можете налаштувати Doctrine так, щоб він автоматично спрямовував запити на читання до репліки, а запити на запис — до первинної (primary) бази даних. Це зменшує навантаження на первинну базу і покращує продуктивність для застосунків із переважанням читання.

Спершу визначте змінну середовища DATABASE_REPLICA_URL у .env:

# .env
DATABASE_REPLICA_URL="mysql://replica_user:replica_password@replica-host:3306/db_name?serverVersion=8.0.37"

Потім налаштуйте репліки у своїй конфігурації Doctrine:

# config/packages/doctrine.yaml
when@prod:
    doctrine:
        dbal:
            url: '%env(resolve:DATABASE_URL)%'
            replicas:
                replica1:
                    url: '%env(resolve:DATABASE_REPLICA_URL)%'
// config/packages/doctrine.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return App::config([
    'doctrine' => [
        'dbal' => [
            'connections' => [
                'default' => [
                    'url' => env('DATABASE_URL')->resolve(),
                    'replica' => [
                        'replica1' => [
                            'url' => env('DATABASE_REPLICA_URL')->resolve(),
                        ],
                    ],
                ],
            ],
            'default_connection' => 'default',
        ],
    ],
]);

Ви можете додати стільки реплік, скільки потрібно (наприклад, replica2, replica3). Коли налаштовано кілька реплік, Doctrine випадково обирає одну під час підключення до репліки і продовжує використовувати її для подальших операцій читання в цьому зʼєднанні.

З такою конфігурацією Doctrine використовує клас-обгортку PrimaryReadReplicaConnection із Doctrine DBAL, який вирішує, куди спрямувати кожну операцію з базою даних:

  • Операції читання (наприклад, fetchAllAssociative(), executeQuery()) надсилаються до репліки;
  • Операції запису (наприклад, executeStatement()) і транзакції надсилаються до первинної бази;
  • Щойно було використано первинну базу, усі подальші операції в цьому зʼєднанні також використовують первинну, що забезпечує узгодженість «читай те, що записав» (read-your-writes).

Маршрутизація ґрунтується на тому, який метод DBAL викликає ваш код, а не на розпізнаванні на рівні SQL. Якщо ви виконаєте запит на запис через метод читання на кшталт executeQuery(), його буде надіслано до репліки. Завжди використовуйте відповідні методи DBAL (executeStatement() для записів, executeQuery() для читань), щоб забезпечити правильну маршрутизацію.

У довготривалих процесах (наприклад, обробники Messenger або режим worker у FrankenPHP) екземпляр зʼєднання повторно використовується між повідомленнями та запитами, тож поведінка «перемкнутися на первинну» діє протягом усього життя цього екземпляра зʼєднання, а не лише одного HTTP-запиту. Перемикання назад на репліку треба робити явно (див. нижче).

Порада: встановіть опцію keep_replica у true, щоб зʼєднання з реплікою лишалося відкритим після використання первинної бази. Це не змінює автоматичної маршрутизації: щойно обрано первинну, методи читання на кшталт executeQuery() продовжують її використовувати. Ця опція дозволяє явно перемкнутися назад на репліку викликом $connection->ensureConnectedToReplica(), що корисно в довготривалих процесах. Без keep_replica цей метод не має ефекту, бо після першого запису зʼєднання з реплікою замінюється первинним:

# config/packages/doctrine.yaml
when@prod:
    doctrine:
        dbal:
            url: '%env(resolve:DATABASE_URL)%'
            keep_replica: true
            replicas:
                replica1:
                    url: '%env(resolve:DATABASE_REPLICA_URL)%'

Примусове використання первинного зʼєднання

У деяких випадках вам може знадобитися примусово задіяти первинне зʼєднання для запиту на читання (наприклад, одразу після запису, щоб забезпечити узгодженість даних). Це можна зробити викликом методу ensureConnectedToPrimary():

// src/Controller/ProductController.php
namespace App\Controller;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class ProductController extends AbstractController
{
    public function index(Connection $connection): Response
    {
        if ($connection instanceof PrimaryReadReplicaConnection) {
            $connection->ensureConnectedToPrimary();
        }

        // наступний запит буде виконано на первинній базі
        $result = $connection->fetchAllAssociative('SELECT * FROM product');

        // ...
    }
}

Перевірка instanceof гарантує, що код працює в усіх середовищах: у продакшені, де налаштовано репліку, $connection є екземпляром PrimaryReadReplicaConnection; у розробці без реплік — це звичайний екземпляр Connection.

Реєстрація власних типів зіставлення (Mapping Types)

Ви можете зареєструвати власні типи зіставлення через конфігурацію Symfony. Їх буде додано до всіх налаштованих зʼєднань. Докладніше про власні типи зіставлення читайте в розділі Custom Mapping Types документації Doctrine.

# config/packages/doctrine.yaml
doctrine:
    dbal:
        types:
            custom_first:  App\Type\CustomFirst
            custom_second: App\Type\CustomSecond
// config/packages/doctrine.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use App\Type\CustomFirst;
use App\Type\CustomSecond;

return App::config([
    'doctrine' => [
        'dbal' => [
            'types' => [
                'custom_first' => CustomFirst::class,
                'custom_second' => CustomSecond::class,
            ],
        ],
    ],
]);

Реєстрація власних типів зіставлення у SchemaTool

SchemaTool використовується для інспектування бази даних, щоб порівняти схему. Для виконання цього завдання йому потрібно знати, який тип зіставлення слід використати для кожного типу бази даних. Реєстрацію нових можна зробити через конфігурацію.

Тепер зіставимо тип ENUM (який Doctrine DBAL не підтримує за замовчуванням) із типом зіставлення text:

# config/packages/doctrine.yaml
doctrine:
    dbal:
        mapping_types:
            enum: text
// config/packages/doctrine.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return App::config([
    'doctrine' => [
        'dbal' => [
            'mapping_types' => [
                'enum' => 'text',
            ],
        ],
    ],
]);

У Doctrine DBAL 3 ви також можете зіставити enum зі string, але це більше не працює в DBAL 4, де стовпці string вимагають явної довжини. Зіставлення з text працює в обох версіях.

Порада: Doctrine DBAL 4.2 додав нативну підтримку типу ENUM для MySQL і MariaDB. Якщо ви використовуєте DBAL 4.2 або новіший, стовпці ENUM інспектуються нативно, тож вам не потрібно реєструвати для них жодного власного типу зіставлення.

ЯК ЦЯ СТОРІНКА ВИГЛЯДАЄ В ПОШУКУ
phpukraine.com/docs/symfony/dbal
DBAL — Symfony документація українською
DBAL у Symfony 8.1: переклад офіційної документації українською. Оновлено 5 вересня 2026. Приклади коду, пояснення та посилання на питання зі співбесід.
Стан перекладу

Перекладаємо з офіційної документації, розділ за розділом, і не ховаємо недоперекладене. Помітили неточність у терміні чи реченні: напишіть, виправимо.

79%
Готовності
5
У роботі
0
Ще не перекладено
Глосарій термінів