L’objet Zend_Db_Select

L’objet Zend_Db_Select du framework Zend (ZF1) sert à représenter une requête SQL de type SELECT incluant des méthodes orientées objets permettant de construire une requête morceau par morceau. Ce court billet détaille un peu la construction d’une requête incluant sous-requête et jointure.

La requête SQL

Voici le SQL que nous voulons représenter à la façon Zend_Db_Select. Pour avoir une idée du schéma, on dispose d’une base de données représentant une gestion de biens, certains biens pouvant être groupés (par exemple, on choisit de grouper des biens individuels CPU, RAM et carte mère dans un bien ordinateur). Cette requête rapatrie ces groupes. On sélectionne les biens de type group d’une table goods (ayant un champ group égal à GRP), le détail des articles sont extraits de la table articles (JOIN) et on compte le nombre d’articles dans le groupe :

SELECT
	aa.*,
	(SELECT COUNT(barcode) FROM goods WHERE group = aa.barcode) AS items
	FROM (
		SELECT a.description, g.* FROM goods AS g
		JOIN articles AS a ON a.code = g.code
			WHERE g.group = "GRP"
	) aa

Rien de bien compliqué SQLement parlant, mais la traduction en utilisant Zend_Db_Select peut être un peu délicate, au début.

Objets Select

L’opération consiste à découper toutes chaque sous-requête et de les assembler à la fin. Voici le code :

// Première requête avec JOIN
$s1 = $db->select()
		->from(
			array('g' => 'goods'),
			array(
				'barcode',
				'quantity',
				'price'
			)
		)
		->join(
			array('a' => 'articles'),
			'a.code = g.code'
		)
		->where('g.group = ?', 'GRP');

// Requête contenant le COUNT
$s2 = $db->select()
		->from(
			'goods',
			array('COUNT(barcode)')
		)
		->where('group = ?', new Zend_Db_Expr('aa.barcode'));

// On assemble le tout
$select = $db->select()
		->from(
			array('aa' => new Zend_Db_Expr('(' . $s1 . ')')),
			array(
				'aa.*',
				'items' => new Zend_Db_Expr('(' . $s2 . ')')
			)
		);

$resultSet = $db->fetchAll($select);

On voit que $s1 représente le SELECT qui liste les groupes, contenu dans le SELECT principal. $2 est celui qui compte le nombre d’article(s) dans un groupe. Et enfin on assemble tout cela dans le $select final que l’on peut exécuter.
A noter l’utilisation de Zend_Db_Expr pour injecter une simple expression.

Conclusion

Manipuler des requêtes un peu complexes avec ZF peut faire peur de prime abord et on peut vouloir se rabattre sur des requête brutes (en utilisant directement Zend_Db_Statement par exemple avec query()), mais lorsque l’on met un peu les mains dedans, c’est un outil tout à fait avancé et puissant qui permet de faire beaucoup de choses tout en restant à manipuler des objets.