FluentPDO – malý a šikovný „SQL query builder“ pre PDO
- Marek Lichtner
- Člen | 6
Cez Vianoce som si vytvoril nový db layer (query builder). Prečo?
Na väčšinu vecí používam NotORM, ale občas som si potreboval vytvoriť zložitejšie SQL dotazy s niekoľkými JOINmy a v NotORM to bolo dosť zložité. Potreboval som niečo veľmi jednoduché, čo ma nebude nijako obmedzovať pri vytváraní SQL dotazov a bude spájať výhody NotORM, Nette\Database a dibi. NotORM resp. Nette\Database sa snaží vyhýbať JOINom, čo je iste efektívnejšie, ale nedá sa v tom si z chuti zaJOINovať ;-) Tak som si vytvoril FluentPDO.
Pozrieť a stiahnuť sa to dá na githube: https://github.com/…er/fluentpdo
Krátke predstavenie:
Pripojenie
<?php
include "libs/FluentPDO.php";
$pdo = new PDO("mysql:dbname=xxx", "root");
$fpdo = new FluentPDO($pdo);
?>
V nette mám potom tri služby $pdo, $notorm, $fpdo
a v danej
situácii použijem vždy to, čo je vhodnejšie.
Základné použitie
<?php
$query = $fpdo->from('article')
->where('published_at > ?', $date)
->orderBy('published_at DESC')
->limit(5);
if ($user_id) {
$query = $query->where('user_id', $user_id);
}
foreach ($query->execute() as $row) {
echo "$row[title]\n";
}
?>
Ako vidieť API je odvodené z SQL. Okrem toho je kód komentovaný, takže
šikovné IDEčka ako netbeans vám budú napovedať. Funkcia
execute()
vracia PDOStatement.
Šikovný JOIN builder
Joiny je možné zapísať celé:
<?php
$query = $fpdo->from('article')
->innerJoin('user ON user.id = article.user_id');
?>
ak v databáze dodržujete konvencie primárnych a cudzích kľúčov stačí zapísať:
<?php
$query = $fpdo->from('article')->innerJoin('user');
?>
spätná referencia sa robí rovnako ako v NotORM cez dvojbodku:
<?php
$query = $fpdo->from('user')->innerJoin('article:');
?>
A pokiaľ použijete položku z inej tabuľky v
select(), where(), orderBy()
, potom joiny netreba
písať vôbec.
<?php
$query = $fpdo->from('article')->orderBy('user.name');
?>
a FluentPDO pripojí tabuľku user
automaticky (LEFT JOINom).
Tiež je možné urobiť aj toto:
<?php
$query = $fpdo->from('comment')
->select('user.name AS comment_author')
->select('article.user.name AS article_author')
->where('comment:user.country = ?', $country_id);
?>
Ako vidíte FluentPDO je silne inšpirované NotORM. Zámerne som API FluentPDO urobil čo najpodobnejšie NotORM, aby bolo možné medzi nimi plynulo prechádzať.
Záver
Prístup NotORM (Nette\Database) je predsa len trochu iný a vyžaduje iné myslenie a niekomu to nemusí vyhovovať. FluentPDO využíva štadardný prístup budovania SQL dotazu. FluentPDO je možné využívať aj samostatne, ale na rozdiel od NotORM, je to len šikovnejší „query builder“, nič viac nič menej…
Zatiaľ som implementoval len SELECT. Dotazy INSERT, UPDATE, DELETE som doteraz nepotreboval implementovať, sú väčšinou jednoduché, na tie používam NotORM. Ak by ste našli nejaké chyby, budem rád ak ma na ne upozorníte.
Podrobné API nájdete na stránke projektu: https://github.com/…er/fluentpdo
Editoval Marek Lichtner (5. 1. 2012 0:53)
- Tomáš Votruba
- Moderator | 1114
Pěkná práce. Jestli opravdu používáš nejčastěji Notorm, zkus kouknout na toto elegantní řešení (a zvaž, zda ti k něčemu bude :)):
- http://sql-cross-queries.freexit.eu/notorm/#8 (příklad)
- https://github.com/…ull/32/files (drobná úprava notorm)
Příklad použití:
$notorm->table()->join("table2", "LEFT JOIN table2 ON table.user_id = table2.car_id")
->select("table.*, table2.*");
Editoval Schmutzka (6. 1. 2012 4:06)
- Marek Lichtner
- Člen | 6
Dík za tip, určite to použijem. A čo Jakub nechce to tam pridať?
Možno keby som o tejto tvojej úprave vedel skôr, tak by som nemal až takú motiváciu robiť FluentPDO ;-) Neviem prečo ma nenapadlo upraviť priamo NotORM. Asi preto, že FluentPDO bolo pre mňa také malé programátorské cvičenie, hračka cez Vianoce ;-)
Možno by som ešte to tvoje riešenie trochu upravil, nestačí jeden parameter?
<?php
$notorm->table()
->join("LEFT JOIN table2 ON table.user_id = table2.car_id");
?>
názov sa predsa dá zistiť z toho reťazca jednoduchým regulárnym výrazom (aj keby tam bol alias) nejako takto: https://github.com/…luentPDO.php#L199
Editoval Marek Lichtner (6. 1. 2012 21:27)