Drupal 8 - Les EntityQuery par l'exemple

Posté le Mardi 26 septembre 2017 - 08:24
Dernière mise à jour le Mercredi 6 décembre 2017 - 16:40
Entity Query

Remplacement des Entity Field Query en drupal 7, les Entity Query permettent d'effectuer des requêtes sur nos types d'entités, (custom ou non) selon leurs propriétés ou leurs champs (fields).

Elles sont une bonne solution pour faire des queries même avancées, sans avoir à faire des jointures à en perdre la tête.

Un exemple simple

Récupération et chargement de l'ensemble des utilisateurs activés.

  1. //On commence par donner le type d'entité que l'on souhaite « requêter »
  2. $query = \Drupal::entityQuery('user');
  3. //On ajoute une condition, ici « status = 1 » pour ne récupérer que les utilisateurs actifs
  4. $query->condition('status', 1);
  5. //On lance la requête et récupère les ids des utilisateurs.
  6. $users_ids = $query->execute();
  7. //on charge les utilisateurs en question
  8. $users = User::loadMultiple($users_ids);

Que peut-on peut requêter ?

Sous drupal 8, tout est entité (ou presque), on peut ainsi faire des requêtes sur :

  • Les noeuds
  • Les blocs
  • Les utilisateurs
  • Les menus
  • Les éléments de menus
  • Nos types d'entités custom
  • ...

Bref, beaucoup de chose !

La déclaration du type d'entité se fait lors de la génération de la requête :

Pour requêter les utilisateurs

$query = \Drupal::entityQuery('user');

Pour requêter les noeuds

$query = \Drupal::entityQuery('node');

Pour les termes de taxonomie

$query = \Drupal::entityQuery('taxonomy_term');

Les conditions

$query->condition(champ_ou_propriété, valeur, opérateur);

Le champ sur lequel on fait une condition peut -être soit une propriété (nid, changed, created, title, name...) ou bien un champ « field » (field_tags, field_image...)

Exemple en requetant les noeuds de type « produit » :

  1. $query = \Drupal::entityQuery('node');
  2. $query->condition('type', 'produit');

Par défaut l'opérateur est : = (égal)

$query->condition('uid', 1); // uid = 1

mais on peut évidement le spécifier :

$query->condition('uid', $user->id(), '<>'); // uid "différent de" 1

On peut utiliser le IN, afin de, par exemple récupérer et charger tous les users en fonction d'un field "interest" qui fait référence à des termes de taxonomies :

  1. $interests = [127, 128, 27];
  2. $query = \Drupal::entityQuery('user');
  3. $query->condition('field_interests', $interests, 'IN');
  4. $profils_similaires = $query->execute();
  5.  
  6. $users = User::loadMultiple($profils_similaires);

Avec un "LIKE", afin de tester le même département :

$query->condition('field_adresse_zipcode', substr($code_postal, 0, 2).'%', 'LIKE');

Plus propre en utilisant db_like qui fait un échappement

  1. $query = \Drupal::entityQuery('taxonomy_term');
  2. $query->condition('vid', 'tags');
  3. $query->condition('name', '%' . db_like($keyword) . '%', 'like');
  4. $terms = Term::loadMultiple($query->execute());

Conditions multiples

Aussi on peut ajouter plusieurs conditions, ici je fais un test sur la date de naissance, qu'elle soit bien comprise entre $min_date & $max_date :

  1. $query = \Drupal::entityQuery('user');
  2. $query->condition('field_interests', $interests, 'IN');
  3. $query->condition('field_birthday', $min_date->format('Y-m-d'), '<');
  4. $query->condition('field_birthday', $max_date->format('Y-m-d'), '>');
  5. $profils_similaires = $query->execute();
  6.  
  7. $users = User::loadMultiple($profils_similaires);

Avec des conditions Or

On peut utiliser des conditions logiques « OR », ici je veux récuperer les utilisateurs qui ont les mêmes centres d'intérêts (field_interests) OU qui sont manuellement mis en avant (field_pinned)

  1. $query = \Drupal::entityQuery('user');
  2.  
  3. $condition_or = $query->orConditionGroup();
  4. $condition_or->condition('field_pinned',1);
  5. $condition_or->condition('field_interests', $interests, 'IN');
  6.  
  7. $query->condition($condition_or);
  8.  
  9. $profils_similaires = $query->execute();
  10.  
  11. $users = User::loadMultiple($profils_similaires);

Avec des conditions OR et AND

On peut faire des conditions un peu plus balaises, avec ici donc : soit les utilisateurs mis en avant (field_pinned) OU (qui ont les même centres d'intérêts (field_interest) ET qui sont nés après $max_date ET avant $min_date :

  1. $query = \Drupal::entityQuery('user');
  2.  
  3. $condition_or = $query->orConditionGroup();
  4. $condition_or->condition('field_pinned',1);
  5.  
  6. $condition_and = $query->andConditionGroup();
  7.  
  8. $condition_and->condition('field_interests', $interests, 'IN');
  9. $condition_and->condition('field_birthday', $min_date->format('Y-m-d'), '<');
  10. $condition_and->condition('field_birthday', $max_date->format('Y-m-d'), '>');
  11.  
  12. $condition_or->condition($condition_and);
  13.  
  14. $query->condition($condition_or);
  15.  
  16. $profils_similaires = $query->execute();
  17.  
  18. $users = User::loadMultiple($profils_similaires);

Gestion de la pagination et du nombre de résultats

$query->range(0, 20);

Gestion du tri

$query->sort('created');

ou en précisant le sens :

$query->sort('field_birthday', 'ASC');

Compter le nombre de résultats

  1. $query = \Drupal::entityQuery('node');
  2. $query->condition('type', 'produit');
  3. $nb_resultats = $query->count()->execute();

 

 

Ajouter un commentaire

Ne sera pas publié

HTML restreint

  • Balises HTML autorisées : <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Les lignes et les paragraphes vont à la ligne automatiquement.
  • Les adresses de pages web et les adresses courriel se transforment en liens automatiquement.
CAPTCHA
Désolé, pour ça, mais c'est le seul moyen pour éviter le spam...