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.
- Connection Aplikace získá Connection s konfigurací driveru, databázové platformy a případných mapovaných typů.
- Dotaz SQL lze napsat přímo nebo sestavit přes QueryBuilder. QueryBuilder skládá syntaxi, ale nenahrazuje znalost SQL ani datového modelu.
- 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.
- Provedení executeQuery a fetch metody vracejí data z čtení. executeStatement provede zápis a vrací počet zasažených řádků.
- 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.