FluentPDO – malý a šikovný „SQL query builder“ pre PDO

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Marek Lichtner
Člen | 6
+
0
-

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
+
0
-

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 :)):

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
+
0
-

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)