web-dev-qa-db-fra.com

Exclusion de champs vides (Null) lors de l'utilisation de la condition de requête EntityFieldQuery

Est-il possible de sélectionner toutes les entités dont le champ xyz est vide?

J'ai essayé quelque chose comme ça:

->fieldCondition('field_name', 'value', NULL, 'IS NOT NULL');

Cependant, cela ne semble pas fonctionner.

Des idées?

30
David Barratt

Si vous regardez sur la page de documentation fieldCondition , vous verrez l'avertissement suivant:

Notez que les entités avec des valeurs de champ vides seront exclues des résultats EntityFieldQuery lors de l'utilisation de cette méthode.

Vérifier si un champ existe ou non a été ajouté à entityFieldQuery dans Drupal 8, mais malheureusement ne sera pas rétroporté vers Drupal 7 =.

Il existe différentes méthodes pour y parvenir:

  1. En utilisant une balise et hook_query_TAG_alter comme mentionné par @Clive, voir commentaire 4 sur le Drupal pour un exemple;
  2. Recherchez d'abord toutes les entrées non NULL, puis interrogez toutes les entrées à l'exception des précédentes, comme décrit dans la réponse de @ seddonym et dans commentaire 5 sur le Drupal ;
  3. Vous pouvez écrire votre requête en utilisant SelectQuery plutôt que EntityfieldQuery en tant que tel:

_

$q = db_select('node', 'n');
$q->fields('n', array('type'))
  ->condition('n.type', 'my_node_type', '=')
  ->addJoin('LEFT', 'field_data_field_my_field', 'f', 'f.entity_id = n.nid');
$q->isNull('f.value');
$r = $q->execute();
19
Alice Heaton

Vous pouvez utiliser != NULL, mais vous ne pouvez pas utiliser = NULL pour certaines raisons.

Ceci est ma solution de contournement.

  //Get all the entities that DO have values
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'MY_TYPE')
    ->fieldCondition('field_MY_FIELD', 'value', 'NULL', '!=');
  $result = $query->execute();

  if (is_array(@$result['registration'])) {
    //Now get all the other entities, that aren't in the list you just retrieved
    $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'MY_TYPE')
      ->entityCondition('entity_id', array_keys($result['MY_TYPE']), 'NOT IN');
    $result_two = $query->execute(); 
  }
15
seddonym

La réponse courte est que, directement, non, vous ne pouvez pas (voir EntityFieldQuery ne prend pas en charge isNull ou isNotNull ). Si je me souviens bien, c'est un effet secondaire du fait que EntityFieldQuery utilise uniquement INNER JOIN Pour joindre les tables.

Il existe cependant une solution de contournement, qui implique l'utilisation de hook_query_TAG_alter() et l'ajout d'une balise à votre EntityFieldQuery, il y a un exemple dans le dernier commentaire de la page à laquelle je suis lié au dessus de.

10
Clive

Selon la documentation vous pouvez utiliser null et isnull; il a juste une façon spécifique de l'écrire.

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'article')
  ->propertyCondition('status', 1)
  ->fieldCondition('field_news_types', 'value', 'spotlight', '=')
  ->fieldCondition('field_photo', 'fid', 'NULL', '!=')
  ->fieldCondition('field_faculty_tag', 'tid', $value)
  ->fieldCondition('field_news_publishdate', 'value', $year. '%', 'like')
  ->range(0, 10)
  ->addMetaData('account', user_load(1)); // run the query as user 1

$result = $query->execute();

if (isset($result['node'])) {
  $news_items_nids = array_keys($result['node']);
  $news_items = entity_load('node', $news_items_nids);
}
10
giorgio79

Dans Drupal 7 veuillez vérifier la solution de contournement suivante proposée ici :

Enregistrez la balise pour modifier l'instance de requête:

<?php
/**
 * Implements hook_query_TAG_alter()
 */
function MYMODULE_query_node_is_not_tagged_alter(QueryAlterableInterface $query) {
  $query->leftJoin('field_data_field_tags', 'o', 'node.nid = o.entity_id AND o.entity_type = :entity_type');
  $query->isNull('o.field_tags_tid');
}
?>

Obs.: Cette modification de balise de requête ne fonctionne que pour le type d'entité "nœud". Ne confondez pas les "field_tags" liés au vocabulaire des "Tags", il peut en être d'autres comme les "Catégories".

Obtenez tous les nœuds qui n'ont pas encore été balisés en utilisant EntityFieldQuery, regardez la méthode addTag ():

<?php
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'news')
  ->addTag('node_is_not_tagged')
  ->propertyCondition('status', 1);
$result = $query->execute();
?>

Autre exemple:

  $result = $query
    ->entityCondition('entity_type', 'node')
    ->propertyCondition('type', 'my_content_type')
    ->fieldCondition('field_mine_one', 'value', '', '<>')
    ->fieldCondition('field_mine_two', 'value', '', '<>')
    ->addTag('my_custom_tag')
    ->deleted(FALSE)
    ->propertyOrderBy('changed', 'DESC')
    ->range(0, $my_range_value)
    ->execute();

Ensuite, j'ai implémenté hook_query_TAG_alter tirant parti du fait que my_custom_tag n'est défini que par moi:

/**
 * Implements hook_query_TAG_alter()
 */
function MYMODULE_query_TAG_alter(QueryAlterableInterface $query) {
  $query->leftJoin('field_data_field_other', 'o', 'node.nid = o.entity_id');
  $query->isNull('o.field_other_value');
}

Un autre exemple:

<?php
  //Get all the entities that DO have values
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'MY_TYPE')
    ->fieldCondition('field_MY_FIELD', 'value', 'NULL', '!=');
  $result = $query->execute();

  if (is_array(@$result['registration'])) {
    //Now get all the other entities, that aren't in the list you just retrieved 
    $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'MY_TYPE')
      ->entityCondition('entity_id', array_keys($result['MY_TYPE']), 'NOT IN');
    $result_two = $query->execute();  
  }
?>

Exemple plus complet ci-dessous qui charge un tas de nœuds sur une tâche cron qui vide les références de termes de taxonomie et applique certaines modifications:

/**
 * Implements hook_cron().
 */
function MYMODULE_cron() {
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', 'property')
    ->propertyOrderBy('changed', 'DESC')
    ->addTag('type_is_null')
    ->range(0,50); // Maximum of 50.
  $result = $query->execute();

  if (!empty($result['node'])) {
    $nids = array_keys($result['node']);
    $nodes = node_load_multiple($nids);

    foreach ($nodes as $node) {
      // do_some_stuff($node);
    }
  }
}

/**
 * Implements hook_query_TAG_alter()
 */
function MYMODULE_query_type_is_null_alter(QueryAlterableInterface $query) {
  $query->leftJoin('field_data_field_foo', 'f', 'node.nid = f.entity_id AND f.entity_type = :entity_type');
  $query->isNull('f.field_foo_tid'); // Check name by SQL: DESC field_data_field_foo

  $query->leftJoin('field_data_field_bar', 'b', 'node.nid = b.entity_id AND b.entity_type = :entity_type');
  $query->isNull('b.field_bar_tid'); // Check name by SQL: DESC field_data_field_bar
}
5
kenorb

Vous devez mettre Null entre guillemets.

->fieldCondition('field_name', 'value', 'NULL', '!=');
3
Sharique

Corrigez-moi si j'ai tort, s'il-vous plait. Il semble qu'il faut simplement

$query->fieldCondition('field_name');

pour exclure tous les nœuds avec un champ vide field_name o_O

Testé en Drupal version >= 7.43.

2
leymannx