Slovník pojmů

Doctrine DBAL

Doctrine DBAL dává PHP aplikaci přímou, ale strukturovanou cestu k relační databázi. Hodí se pro explicitní SQL, dávkové zpracování i transakční operace, kde objektové mapování není nejpřesnější nástroj.

Stručná definice

Databázová vrstva mezi aplikací a konkrétním SQL driverem.

Doctrine DBAL, z anglického Database Abstraction Layer, poskytuje připojení k databázi, parametrizované dotazy, převody hodnot, práci s výsledky, transakce a QueryBuilder. Aplikace tak nemusí pro každý driver ručně řešit detaily PDO nebo rozdíly některých databázových platforem, přesto zůstává blízko SQL a reálnému modelu tabulek.

DBAL je součást ekosystému Doctrine a používá jej také Doctrine ORM, ale lze ho používat samostatně. ORM mapuje objekty a asociace na tabulky a sleduje jejich změny; DBAL naopak dovoluje přesně říct, jaký SELECT, INSERT či UPDATE má databáze vykonat. Databázová entita proto automaticky není doménový objekt a SQL přes DBAL není selhání architektury.

K čemu se používá

Dotazy, které mají mít viditelnou podobu a jasnou cenu

DBAL je praktický tam, kde aplikace potřebuje pracovat s relačními daty přímo, bezpečně a bez budování celé objektové mapy.

  • reportingové a agregační dotazy nad objednávkami, sklady nebo platbami
  • dávkové importy a exporty, kde je důležitý průběžný tok dat a malá paměťová stopa
  • atomické změny zásoby, stavů nebo idempotentních integračních záznamů
  • specializované SQL funkce a optimalizace konkrétní databázové platformy
  • repozitáře a read modely, pro které by načítání celého grafu ORM entit bylo zbytečné

Praktický příklad

Přehled zaplacených objednávek bez sestavování entit

Administrace potřebuje rychle zobrazit počet zaplacených objednávek pro konkrétní obchod. Pro tento read model není nutné načítat objednávky, položky a zákazníky jako entity. Jediný parametrizovaný dotaz vrátí skalární hodnotu a vazba na Connection je předaná přes konstruktor, takže se dá třída v testu nahradit nebo ověřit integračně.

Hodnota obchodu i stav objednávky jsou předány jako parametry, nikoliv složené do SQL řetězce. Pokud by se dynamicky volil název sloupce nebo řazení, parameter nestačí: takový identifikátor musí pocházet z pevného seznamu povolených možností.

<?php

use Doctrine\DBAL\Connection;

final class OrderStatistics
{
    public function __construct(private Connection $connection)
    {
    }

    public function paidCountForStore(string $storeCode): int
    {
        return (int) $this->connection->fetchOne(
            'SELECT COUNT(*) FROM orders WHERE store_code = :store AND status = :status',
            ['store' => $storeCode, 'status' => 'paid'],
        );
    }
}

Jak funguje

Od připojení po výsledek nebo potvrzenou změnu

DBAL odděluje vytvoření dotazu, předání hodnot, jeho provedení a případnou transakční hranici.

  1. Connection Aplikace získá Connection s konfigurací driveru, databázové platformy a případných mapovaných typů.
  2. Dotaz SQL lze napsat přímo nebo sestavit přes QueryBuilder. QueryBuilder skládá syntaxi, ale nenahrazuje znalost SQL ani datového modelu.
  3. Parametry a typy Hodnoty uživatele či integrace se předávají placeholderem a parametrem; DBAL je připraví pro driver a podle potřeby převede typ.
  4. Provedení executeQuery a fetch metody vracejí data z čtení. executeStatement provede zápis a vrací počet zasažených řádků.
  5. Transakce Související změny se uzavřou do transakce. Při chybě se musí změny správně vrátit nebo nechat výjimku propadnout řídicí vrstvě.

Hlavní části a pojmy

Explicitní databázová práce neznamená ruční skládání řetězců.

DBAL poskytuje malé stavební bloky. Jejich správné použití závisí na tom, zda jde o čtení, zápis, souběh nebo změnu schématu.

Connection a platforma

Connection zprostředkuje driver, transakce a databázovou platformu. Abstrakce pomáhá s běžnými operacemi, ale specifické SQL a výkonové vlastnosti dané databáze nezmizí.

Parametrizované dotazy

Placeholdery oddělují SQL strukturu od hodnot. Chrání proti SQL injection pro hodnoty; názvy tabulek, sloupců a směry řazení se parametrizovat nedají a musí být řízené allowlistem.

QueryBuilder

Usnadňuje skládání podmíněných částí dotazu a parametrů. Sám o sobě však nedělá uživatelský vstup bezpečným; hodnoty se stále vážou přes parametry.

Výsledky a typy

fetchOne, fetchAssociative nebo iterovatelné výsledky podporují různé tvary čtení. Typová konverze je užitečná pro datumy či identifikátory, ale návratová data je pořád nutné zpracovat vědomě.

Transakce

DBAL nabízí explicitní begin, commit a rollback i callbackovou transakční práci. Transakce chrání lokální databázový celek, ne komunikaci s platební bránou nebo jiným API.

Vztah k ostatním nástrojům

Stejnou databázi lze používat různými vrstvami podle úlohy.

Není nutné rozhodnout se jednou provždy pro ORM nebo SQL. V jedné aplikaci mohou vedle sebe existovat entity, DBAL read modely a dobře zdůvodněné databázové operace.

Doctrine ORM
ORM řeší entity, Unit of Work a asociace. DBAL se hodí na explicitní dotaz či zápis, kde by entity přidaly zbytečnou režii nebo skryly SQL.
Přímé PDO
PDO je nižší API. DBAL často používá PDO, ale může pracovat i nad jiným nativním driverem; přidává konzistentnější práci s platformou, typy a QueryBuilderem, ale nezbavuje vývojáře odpovědnosti za návrh dotazu.
Databázové migrace
Migrace mění tabulky a indexy. DBAL dotazy musí odpovídat verzím schématu, které mohou během nasazení krátce existovat vedle sebe.
Framework a DI container
Symfony i jiné frameworky mohou Connection vytvořit a nakonfigurovat. Runtime injection není totéž co architektonická hranice: databáze nemá téct do každé vrstvy jen proto, že je dostupná.

Výhody a omezení

Přímé SQL dává kontrolu, ale vyžaduje odpovědnost.

Přínosy

  • viditelný SQL dotaz a přesné řízení načítaných dat
  • parametrizace, typy a transakce bez ruční práce s každým driverem
  • vhodné pro agregace, dávky a výkonově citlivé read modely
  • možnost použít ORM i DBAL vedle sebe podle charakteru operace

Omezení a chyby

  • QueryBuilder nechrání automaticky před vložením neověřené hodnoty do SQL
  • abstrakce nezaručuje plnou přenositelnost specifického SQL mezi databázemi
  • dlouhá transakce či N+1 dotaz zůstávají problémem i přes DBAL
  • DBAL nenahradí constrainty, indexy, monitoring ani pochopení plánu dotazu

Kdy dává smysl

Použít DBAL tam, kde je SQL důležitou součástí řešení.

DBAL je dobrá volba pro import objednávek, reporting, dávkové úlohy, cílenou aktualizaci zásob nebo specializovaný dotaz nad PostgreSQL. V těchto situacích bývá přínosné mít parametry, transakci a vrácená data na jednom viditelném místě, místo aby se z obecného ORM modelu skládal nečitelný kompromis.

Na jednoduchou práci s bohatým objektem může být ORM čitelnější. Naopak přímé SQL přes DBAL nemá být univerzální náhradou doménových pravidel v aplikační vrstvě. Kritériem je srozumitelnost, měřitelný provozní přínos a schopnost změnu bezpečně testovat, ne preference konkrétního stylu.

Na co myslet

SQL, transakce a schéma kontrolovat jako jeden celek.

Dobře napsaný DBAL dotaz je malý, parametrizovaný, měřitelný a má jasnou odpovědnost.

  • vázat všechny proměnlivé hodnoty jako parametry a identifikátory vybírat jen z allowlistu
  • pro čtení a zápis používat odpovídající metodu a explicitně pojmenovat očekávaný tvar výsledku
  • držet transakce krátké a nevolat uvnitř nich pomalé externí API
  • ověřit indexy, constrainty a plán důležitých dotazů nad realistickými daty
  • integračně testovat SQL proti skutečnému podporovanému databázovému enginu

Časté otázky

DBAL vedle ORM a databáze

Je Doctrine DBAL totéž co Doctrine ORM?

Ne. DBAL poskytuje připojení, SQL, parametry a transakce. ORM nad podobnou databázovou vrstvou řeší mapování entit, asociace a sledování jejich změn.

Je QueryBuilder automaticky bezpečný proti SQL injection?

Ne. Bezpečnost pro hodnoty vzniká až použitím placeholderů a parametrů. QueryBuilder nesmí dostat neověřený vstup jako kus SQL, název sloupce nebo směr ORDER BY.

Kdy použít DBAL místo ORM?

Typicky pro cílené agregace, dávkové importy, explicitní aktualizace nebo dotaz, kde je SQL důležité pro výkon a čitelnost. Nejde o pravidlo, že jedna vrstva musí vyhrát všude.

Vytvoří DBAL transakci sám?

Ne automaticky pro libovolnou sadu operací. Hranici je třeba zvolit vědomě pomocí transakčních metod či callbacku a ošetřit chybu a případné opakování konfliktu.

Jak pracuji s databázemi v praxi

Databázovou vrstvu volím podle typu operace, ne podle zvyku.

U e-commerce a integrací řeším relační model, explicitní dotazy, transakce i provozní dopady změn dat.

Zavolejte mi

Zavolám vám následující pracovní den mezi 9:00 a 17:00.

Můžete mi také zavolat rovnou.

+420 605 181 728

Nechte mi telefonní číslo a pošlete žádost o zpětné zavolání.

Odesláním souhlasíte se zpracováním údajů pro vyřízení žádosti.