13.Zend Framework 2 et 3

13.7.Les bases de données

13.7.3.Construire la requête SQL

13.7.3.6.where() et Where

13.7.3.6.1.Condition simple

Pour filtrer les résultats impactés par les requêtes (ex: select, update ou delete) on complètera la requête avec la méthode where() qui accepte un paramètre qui peut prendre différentes formes.
La forme la plus simple (mais qui ne répond pas à toutes les problématiques loin de là) c'est le tableau associatif contenant la liste des valeurs attendues pour chacun des champs précisés (les clés du tableau) comme dans l'exemple suivant:
<?php
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;

$db = new Adapter($config); // $config à définir
$sql = new Sql($db);

$nomTable = 'matable';
$where = array('champ1' => 'valeur1',
               'champ2' => 'valeur2');

$requete = $sql->select()
               ->from($nomTable)
               ->where($where);
// Equivalent à SELECT ... WHERE champ1='valeur1' AND champ2='valeur2'
// Reste à exécuter la requête et parcourir les résultats
Il est possible de spécifier NULL comme valeur si l'on souhaite que l'un des champs soit NULL (IS NULL) ou encore spécifier un tableau des valeurs attendues pour une requête de type IN.
<?php
$where = array('champ1' => 'valeur1',
               'champ2' => NULL,
               'champ3' => array('a', 'b', 'c'));

$requete = $sql->select()
               ->from($nomTable)
               ->where($where);
// Equivalent à SELECT ... WHERE champ1='valeur1' AND champ2 IS NULL AND champ3 IN ('a', 'b', 'c')
// Reste à exécuter la requête et parcourir les résultats
Mais impossible ainsi d'utiliser un opérateur autre que égal (pas de plus grand que, plus petit que, etc.), ni utiliser une combinaison autre que AND (pas de OR possible). Pour comparer (dans ce cadre) 2 champs entre eux (et non pas un champ avec une valeur) ou pour faire appel à des fonctions (dans la deuxième partie de l'opérande) il est, en revanche, possible, là encore, de faire appel à l'objet Zend\Db\Sql\Expression[comment?].

13.7.3.6.2.Opérateur AND avec <, >,<=, >=, etc.

Pour une gestion plus fine de la méthode where() vous devez faire appel à l'objet Zend\Db\Sql\Where dont l'essentiel des méthodes est listé dans l'exemple ci-dessous:
<?php
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
use Zend\Db\Sql\Where;

$db = new Adapter($config); // $config à définir
$sql = new Sql($db);

$nomTable = 'matable';
$where = new Where();
$where->between('champ1', 10, 20);              // champ1 BETWEEN 10 AND 20
$where->equalTo('champ2', 'valeur');            // champ2 = 'valeur'
$where->in('champ3', array('A', 'B'));          // champ3 IN ('A', 'B')
$where->isNotNull('champ4');                    // champ4 IS NOT NULL
$where->isNull('champ5');                       // champ5 IS NULL
$where->greaterThan('champ6', 'valeur');        // champ6 > 'valeur'
$where->greaterThanOrEqual('champ7', 'valeur'); // champ7 >= 'valeur'
$where->lessThan('champ8', 'valeur');           // champ8 < 'valeur'
$where->lessThanOrEqual('champ9', 'valeur');    // champ9 <= 'valeur'
$where->like('champ10', 'valeur%');             // champ10 LIKE 'valeur%'

$requete = $sql->select()
               ->from($nomTable)
               ->where($where);
// Reste à exécuter la requête et parcourir les résultats
Même si, avec les fonctions présentées, les contraintes se combinent uniquement avec l'opérateur AND il n'empêche que, grâce à l'objet Where, le champ des possibles est déjà plus vaste... et encore, on ne vous a pas tout dit.
Pour les méthodes pour lesquelles c'est pertinent (à savoir: equalTo(), greaterThan(), greaterThanOrEqualTo(), lessThan(), lessThanOrEqual()) il est possible de comparer non seulement un champ à une valeur mais aussi un champ à un champ (voire une valeur à un champ ou encore une valeur à une valeur). Pour cela, on précisera 2 champs supplémentaires afin d'indiquer via les constantes Where::TYPE_IDENTIFIER (identifiant/champ) et Where::TYPE_VALUE (valeur) si le champ de gauche (puis de droite) est un identifiant de champ ou une valeur. Comme dans l'exemple suivant:
<?php
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
use Zend\Db\Sql\Where;

$db = new Adapter($config); // $config à définir
$sql = new Sql($db);

$nomTable = 'matable';
$where = new Where();
$where->equalTo('champ1', 'champ2',
                Where::TYPE_IDENTIFIER, Where::TYPE_IDENTIFIER); // champ1 = champ2
$where->equalTo('valeur', 'champ3',
                Where::TYPE_VALUE, Where::TYPE_IDENTIFIER);      // 'valeur' = champ3

$requete = $sql->select()
               ->from($nomTable)
               ->where($where);
// Reste à exécuter la requête et parcourir les résultats
Dans ce cas, la requête est équivalente à SELECT ... WHERE champ1=champ2 AND 'valeur'=champ3.

13.7.3.6.3.Opérateur OR

Avec ce que nous avons vu jusque là, il n'a été possible que de combiner les tests avec l'opérateur AND. Pour pouvoir utiliser l'opérateur OR il existe plusieurs options. En voici une: utiliser le mot clé magique or. Ce n'est pas une méthode, ça ne s'emploie pas totalement de la même façon qu'une variable membre classique non plus mais ça fait l'affaire comme dans l'exemple suivant:
<?php
use Zend\Db\Sql\Where;

$where = new Where();
$where->equalTo('champ1', 'valeur')
      ->or
      ->isNull('champ1');

// WHERE champ1='valeur' OR champ1 IS NULL
L'exemple est facile à comprendre car il n'y a que 2 tests combinés par un simple opérateur OR. Cela peut devenir plus complexe lorsqu'il s'agit de combiner des AND et des OR. Heureusement, pour cela aussi il y a une solution.

13.7.3.6.4.Combiner AND et OR avec nest et unnest

Si l'on souhaite combiner de façon simple et claire des tests SQL comme on pourrait le faire naturellement en posant des parenthèses, il faut faire appel aux mot clés magiques nest et unnest. La première est l'équivalent de l'ouverture d'une parenthèse et la seconde à sa fermeture. Et c'est finalement assez simple à utiliser.
<?php
use Zend\Db\Sql\Where;

$where = new Where();
$where->nest
        ->equalTo('champ1', 'valeur')
        ->or
        ->isNull('champ1')
      ->unnest
        ->equalTo('champ2', 'valeur2');

// WHERE (champ1='valeur' OR champ1 IS NULL) AND champ2='valeur2'