Le QueryBuilder Symfony2


Table des matières

Référence
Construire un objet QueryBuilder nouvelle
Travailler avec QueryBuilder
Paramètres de liaison à votre requête
Limiter le résultat
Exécuter une requête
Les classes Expr*
La classe Expr
Méthodes Helper

Référence

http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/query-builder.html

Un QueryBuilder fournit une API qui est conçu pour construire une requête conditionnelle DQL en plusieurs étapes.

Il fournit un ensemble de classes et de méthodes qui est capable de construire des requêtes par programmation, et fournit également une API couramment. Cela signifie que vous pouvez changer entre une méthodologie pour les autres comme vous voulez, et aussi en choisir un, si vous préférez.

Construire un objet QueryBuilder nouvelle

De la même façon que vous créez une requête normale, vous construisez un objet QueryBuilder, simplement fournir le nom de méthode correcte. Voici un exemple de comment construire un objet QueryBuilder:

<?php
// $em instanceof EntityManager

// example1: creating a QueryBuilder instance
$qb = $em->createQueryBuilder();

Une fois que vous avez créé une instance de QueryBuilder, il fournit un ensemble de fonctions utiles d'information que vous pouvez utiliser. Un bon exemple est d'inspecter ce type d'objet qu'est QueryBuilder.

<?php
// $qb instanceof QueryBuilder

// example2: retrieving type of QueryBuilder
echo $qb->getType(); // Prints: 0

Il est actuellement 3 valeurs de retour possibles pour getType ():

Il est possible de récupérer le EntityManager associé de QueryBuilder actuelle, ses DQL et aussi un objet de requête quand vous avez fini la construction de votre DQL.

<?php
// $qb instanceof QueryBuilder

// example3: retrieve the associated EntityManager
$em = $qb->getEntityManager();

// example4: retrieve the DQL string of what was defined in QueryBuilder
$dql = $qb->getDql();

// example5: retrieve the associated Query object with the processed DQL
$q = $qb->getQuery();

En interne, QueryBuilder fonctionne avec une mémoire cache DQL pour augmenter les performances. Tout changement pouvant affecter la DQL généré modifie réellement l'état de QueryBuilder à une étape que nous appelons STATE_DIRTY. Un QueryBuilder peut être dans deux états différents:

Travailler avec QueryBuilder

Toutes les méthodes d'assistance au QueryBuilder s'appuient sur une seule: add(). Cette méthode est responsable de la construction de chaque partie de DQL. Il prend 3 paramètres: $dqlPartName, $dqlPart et $append (default = false)

<?php
// $qb instanceof QueryBuilder

// example6: how to define: "SELECT u FROM User u WHERE u.id = ? ORDER BY u.name ASC" using QueryBuilder string support
$qb->add('select', 'u')
   ->add('from', 'User u')
   ->add('where', 'u.id = ?1')
   ->add('orderBy', 'u.name ASC');

Paramètres de liaison à votre requête

Doctrine supporte la liaison dynamique des paramètres à votre requête, semblable à la préparation de requêtes. Vous pouvez utiliser les deux chaînes et les nombres comme des espaces réservés, bien que les deux ont une syntaxe légèrement différente. De plus, vous devez faire votre choix: mélange deux styles n'est pas autorisée. Paramètres de liaison peut être simplement réalisé comme suit:

<?php
// $qb instanceof QueryBuilder

// example6: how to define: "SELECT u FROM User u WHERE u.id = ? ORDER BY u.name ASC" using QueryBuilder string support
$qb->add('select', 'u')
   ->add('from', 'User u')
   ->add('where', 'u.id = ?1')
   ->add('orderBy', 'u.name ASC');
   ->setParameter(1, 100); // Sets ?1 to 100, and thus we will fetch a user with u.id = 100

Vous n'êtes pas obligé d'énumérer vos espaces réservés comme la syntaxe alternative est disponible:

<?php
// $qb instanceof QueryBuilder

// example6: how to define: "SELECT u FROM User u WHERE u.id = ? ORDER BY u.name ASC" using QueryBuilder string support
$qb->add('select', 'u')
   ->add('from', 'User u')
   ->add('where', 'u.id = :identifier')
   ->add('orderBy', 'u.name ASC');
   ->setParameter('identifier', 100); // Sets :identifier to 100, and thus we will fetch a user with u.id = 100

Notez que des espaces réservés numériques démarrent avec un ? suivi d'un numéro alors que les marqueurs nommés commencer par un : suivie par une chaîne.

Si vous avez plusieurs paramètres pour lier à votre requête, vous pouvez également utiliser setParameters() au lieu de setParameter() avec la syntaxe suivante:

<?php
// $qb instanceof QueryBuilder

// Query here...
$qb->setParameters(array(1 = > 'value for ?1', 2 = > 'value for ?2'));

Obtenir les paramètres déjà lié est facile - il suffit d'utiliser la syntaxe ci-dessus avec "getParameter()" ou "getParameters()":

<?php
// $qb instanceof QueryBuilder

// See example above
$params = $qb->getParameters(array(1, 2));
// Equivalent to
$param  = array($qb->getParameter(1), $qb->getParameter(2));

Remarque: Si vous essayez d'obtenir un paramètre qui n'était pas lié encore, getParameter() retourne simplement NULL.

Limiter le résultat

Afin de limiter un résultat le constructeur de requêtes a certaines méthodes en commun avec l'objet de requêtes qui peuvent être récupérés à partir de EntityManager#createQuery().

<?php
// $qb instanceof QueryBuilder
$offset = (int)$_GET['offset'];
$limit = (int)$_GET['limit'];

$qb->add('select', 'u')
   ->add('from', 'User u')
   ->add('orderBy', 'u.name ASC')
   ->setFirstResult( $offset )
   ->setMaxResults( $limit );

Exécuter une requête

Le QueryBuilder est seulement un objet builder, il n'a aucun moyen de réellement exécuter la requête. En outre, un ensemble de paramètres tels que les indicateurs de requête ne peut pas être mis sur le QueryBuilder lui-même. C'est pourquoi vous devez toujours convertir une instance Générateur de requêtes dans un objet de requête:

<?php
// $qb instanceof QueryBuilder
$query = $qb->getQuery();

// Set additional Query options
$query->setQueryHint('foo', 'bar');
$query->useResultCache('my_cache_id');

// Execute Query
$result = $query->getResult();
$single = $query->getSingleResult();
$array = $query->getArrayResult();
$scalar = $query->getScalarResult();
$singleScalar = $query->getSingleScalarResult();

Les classes Expr*

Lorsque vous appelez add(), avec chaîne, elle évalue en interne une instance de la classe Doctrine\ORM\Query\Expr\Expr\. Voici la même requête de l'exemple 6 écrit en utilisant les classes Doctrine\ORM\Query\Expr\Expr\:

<?php
// $qb instanceof QueryBuilder

// example7: how to define: "SELECT u FROM User u WHERE u.id = ? ORDER BY u.name ASC" using QueryBuilder using Expr\* instances
$qb->add('select', new Expr\Select(array('u')))
   ->add('from', new Expr\From('User', 'u'))
   ->add('where', new Expr\Comparison('u.id', ' = ', '?1'))
   ->add('orderBy', new Expr\OrderBy('u.name', 'ASC'));

Bien sûr, cela est la manière la plus dure de construire une requête DQL dans la doctrine. Afin de simplifier certains de ces efforts, nous introduisons ce que nous appelons une classe helper Expr.

La classe Expr

Pour contourner certaines des questions que méthode add() peut causer, Doctrine créé une classe qui peut être considéré comme une aide pour la construction des expressions. Cette classe est appelée Expr, qui fournit un ensemble de méthodes utiles pour aider à construire les expressions:

<?php
// $qb instanceof QueryBuilder

// example8: QueryBuilder port of: "SELECT u FROM User u WHERE u.id = ? OR u.nickname LIKE ? ORDER BY u.surname DESC" using Expr class
$qb->add('select', new Expr\Select(array('u')))
   ->add('from', new Expr\From('User', 'u'))
   ->add('where', $qb->expr()->orX(
       $qb->expr()->eq('u.id', '?1'),
       $qb->expr()->like('u.nickname', '?2')
   ))
   ->add('orderBy', new Expr\OrderBy('u.name', 'ASC'));

Bien que cela semble toujours aussi complexe, la capacité de programmation de créer les conditions sont la caractéristique principale de Expr. Ici, il est une liste complète des méthodes de helper supportées disponibles:

<?php
class Expr
{
    /** Conditional objects **/

    // Example - $qb->expr()->andX($cond1 [, $condN])->add(...)->...
    public function andX($x = null); // Returns Expr\AndX instance

    // Example - $qb->expr()->orX($cond1 [, $condN])->add(...)->...
    public function orX($x = null); // Returns Expr\OrX instance


    /** Comparison objects **/

    // Example - $qb->expr()->eq('u.id', '?1') = > u.id = ?1
    public function eq($x, $y); // Returns Expr\Comparison instance

    // Example - $qb->expr()->neq('u.id', '?1') = > u.id <> ?1
    public function neq($x, $y); // Returns Expr\Comparison instance

    // Example - $qb->expr()->lt('u.id', '?1') = > u.id < ?1
    public function lt($x, $y); // Returns Expr\Comparison instance

    // Example - $qb->expr()->lte('u.id', '?1') = > u.id <= ?1
    public function lte($x, $y); // Returns Expr\Comparison instance

    // Example - $qb->expr()->gt('u.id', '?1') = > u.id > ?1
    public function gt($x, $y); // Returns Expr\Comparison instance

    // Example - $qb->expr()->gte('u.id', '?1') = > u.id >= ?1
    public function gte($x, $y); // Returns Expr\Comparison instance

    // Example - $qb->expr()->isNull('u.id') = > u.id IS NULL
    public function isNull($x); // Returns string

    // Example - $qb->expr()->isNotNull('u.id') = > u.id IS NOT NULL
    public function isNotNull($x); // Returns string


    /** Arithmetic objects **/

    // Example - $qb->expr()->prod('u.id', '2') = > u.id * 2
    public function prod($x, $y); // Returns Expr\Math instance

    // Example - $qb->expr()->diff('u.id', '2') = > u.id - 2
    public function diff($x, $y); // Returns Expr\Math instance

    // Example - $qb->expr()->sum('u.id', '2') = > u.id + 2
    public function sum($x, $y); // Returns Expr\Math instance

    // Example - $qb->expr()->quot('u.id', '2') = > u.id / 2
    public function quot($x, $y); // Returns Expr\Math instance


    /** Pseudo-function objects **/

    // Example - $qb->expr()->exists($qb2->getDql())
    public function exists($subquery); // Returns Expr\Func instance

    // Example - $qb->expr()->all($qb2->getDql())
    public function all($subquery); // Returns Expr\Func instance

    // Example - $qb->expr()->some($qb2->getDql())
    public function some($subquery); // Returns Expr\Func instance

    // Example - $qb->expr()->any($qb2->getDql())
    public function any($subquery); // Returns Expr\Func instance

    // Example - $qb->expr()->not($qb->expr()->eq('u.id', '?1'))
    public function not($restriction); // Returns Expr\Func instance

    // Example - $qb->expr()->in('u.id', array(1, 2, 3))
    // Make sure that you do NOT use something similar to $qb->expr()->in('value', array('stringvalue')) as this will cause Doctrine to throw an Exception.
    // Instead, use $qb->expr()->in('value', array('?1')) and bind your parameter to ?1 (see section above)
    public function in($x, $y); // Returns Expr\Func instance

    // Example - $qb->expr()->notIn('u.id', '2')
    public function notIn($x, $y); // Returns Expr\Func instance

    // Example - $qb->expr()->like('u.firstname', $qb->expr()->literal('Gui%'))
    public function like($x, $y); // Returns Expr\Comparison instance

    // Example - $qb->expr()->between('u.id', '1', '10')
    public function between($val, $x, $y); // Returns Expr\Func


    /** Function objects **/

    // Example - $qb->expr()->trim('u.firstname')
    public function trim($x); // Returns Expr\Func

    // Example - $qb->expr()->concat('u.firstname', $qb->expr()->concat(' ', 'u.lastname'))
    public function concat($x, $y); // Returns Expr\Func

    // Example - $qb->expr()->substr('u.firstname', 0, 1)
    public function substr($x, $from, $len); // Returns Expr\Func

    // Example - $qb->expr()->lower('u.firstname')
    public function lower($x); // Returns Expr\Func

    // Example - $qb->expr()->upper('u.firstname')
    public function upper($x); // Returns Expr\Func

    // Example - $qb->expr()->length('u.firstname')
    public function length($x); // Returns Expr\Func

    // Example - $qb->expr()->avg('u.age')
    public function avg($x); // Returns Expr\Func

    // Example - $qb->expr()->max('u.age')
    public function max($x); // Returns Expr\Func

    // Example - $qb->expr()->min('u.age')
    public function min($x); // Returns Expr\Func

    // Example - $qb->expr()->abs('u.currentBalance')
    public function abs($x); // Returns Expr\Func

    // Example - $qb->expr()->sqrt('u.currentBalance')
    public function sqrt($x); // Returns Expr\Func

    // Example - $qb->expr()->count('u.firstname')
    public function count($x); // Returns Expr\Func

    // Example - $qb->expr()->countDistinct('u.surname')
    public function countDistinct($x); // Returns Expr\Func
}

Méthodes Helper

Jusqu'à présent nous avons décrit au plus bas niveau (considéré comme la méthode hardcore) la création des requêtes. Il pourrait être utile de travailler à ce niveau à des fins d'optimisation, mais la plupart du temps il est préférable de travailler à un niveau supérieur d'abstraction. Pour simplifier encore plus la façon dont vous créez une requête dans la doctrine, nous pouvons profiter de ce que nous appelons les méthodes Helper. Pour tous les codes de base, il y a un ensemble de méthodes utiles pour simplifier la vie d'un programmeur. Pour illustrer la façon de travailler avec eux, voici le même exemple 6 ré-écrit en utilisant des méthodes de helper QueryBuilder:

<?php
// $qb instanceof QueryBuilder

// example9: how to define: "SELECT u FROM User u WHERE u.id = ?1 ORDER BY u.name ASC" using QueryBuilder helper methods
$qb->select('u')
   ->from('User', 'u')
   ->where('u.id = ?1')
   ->orderBy('u.name', 'ASC');

Les méthodes de helper QueryBuilder sont considérées comme le moyen standard pour construire des requêtes DQL. Bien qu'il soit pris en charge, il devrait être évité d'utiliser des requêtes chaîne de base et grandement encouragés à utiliser les méthodes $qb->expr()->. Voici un exemple de suggestion façon standard pour créer des requêtes:

<?php
// $qb instanceof QueryBuilder

// example8: QueryBuilder port of: "SELECT u FROM User u WHERE u.id = ?1 OR u.nickname LIKE ?2 ORDER BY u.surname DESC" using QueryBuilder helper methods
$qb->select(array('u')) // string 'u' is converted to array internally
   ->from('User', 'u')
   ->where($qb->expr()->orX(
       $qb->expr()->eq('u.id', '?1'),
       $qb->expr()->like('u.nickname', '?2')
   ))
   ->orderBy('u.surname', 'ASC'));

Voici une liste complète des méthodes d'assistance disponible en QueryBuilder:

<?php
class QueryBuilder
{
    // Example - $qb->select('u')
    // Example - $qb->select(array('u', 'p'))
    // Example - $qb->select($qb->expr()->select('u', 'p'))
    public function select($select = null);

    // Example - $qb->delete('User', 'u')
    public function delete($delete = null, $alias = null);

    // Example - $qb->update('Group', 'g')
    public function update($update = null, $alias = null);

    // Example - $qb->set('u.firstName', $qb->expr()->literal('Arnold'))
    // Example - $qb->set('u.numChilds', 'u.numChilds + ?1')
    // Example - $qb->set('u.numChilds', $qb->expr()->sum('u.numChilds', '?1'))
    public function set($key, $value);

    // Example - $qb->from('Phonenumber', 'p')
    public function from($from, $alias = null);

    // Example - $qb->innerJoin('u.Group', 'g', Expr\Join::WITH, $qb->expr()->eq('u.status_id', '?1'))
    // Example - $qb->innerJoin('u.Group', 'g', 'WITH', 'u.status = ?1')
    public function innerJoin($join, $alias = null, $conditionType = null, $condition = null);

    // Example - $qb->leftJoin('u.Phonenumbers', 'p', Expr\Join::WITH, $qb->expr()->eq('p.area_code', 55))
    // Example - $qb->leftJoin('u.Phonenumbers', 'p', 'WITH', 'p.area_code = 55')
    public function leftJoin($join, $alias = null, $conditionType = null, $condition = null);

    // NOTE: ->where() overrides all previously set conditions
    //
    // Example - $qb->where('u.firstName = ?1', $qb->expr()->eq('u.surname', '?2'))
    // Example - $qb->where($qb->expr()->andX($qb->expr()->eq('u.firstName', '?1'), $qb->expr()->eq('u.surname', '?2')))
    // Example - $qb->where('u.firstName = ?1 AND u.surname = ?2')
    public function where($where);

    // Example - $qb->andWhere($qb->expr()->orX($qb->expr()->lte('u.age', 40), 'u.numChild = 0'))
    public function andWhere($where);

    // Example - $qb->orWhere($qb->expr()->between('u.id', 1, 10));
    public function orWhere($where);

    // NOTE: -> groupBy() overrides all previously set grouping conditions
    //
    // Example - $qb->groupBy('u.id')
    public function groupBy($groupBy);

    // Example - $qb->addGroupBy('g.name')
    public function addGroupBy($groupBy);

    // NOTE: -> having() overrides all previously set having conditions
    //
    // Example - $qb->having('u.salary >= ?1')
    // Example - $qb->having($qb->expr()->gte('u.salary', '?1'))
    public function having($having);

    // Example - $qb->andHaving($qb->expr()->gt($qb->expr()->count('u.numChild'), 0))
    public function andHaving($having);

    // Example - $qb->orHaving($qb->expr()->lte('g.managerLevel', '100'))
    public function orHaving($having);

    // NOTE: -> orderBy() overrides all previously set ordering conditions
    //
    // Example - $qb->orderBy('u.surname', 'DESC')
    public function orderBy($sort, $order = null);

    // Example - $qb->addOrderBy('u.firstName')
    public function addOrderBy($sort, $order = null); // Default $order = 'ASC'
}