EntityFieldQuery INNER JOIN

21

Je voudrais exécuter une requête à l'aide de l'objet EntityFieldQuery. J'ai besoin de valeur à la fois du nœud et de la table node_access, donc j'aurais besoin d'utiliser INNER JOIN. À partir de la documentation do, je ne peux pas comprendre comment cela est possible.

Voici ce que j'ai -

$query = new EntityFieldQuery();
$result = $query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'node_access')
->propertyCondition('type', 'external_link')
->propertyCondition('status', 1)
->fieldCondition('gid', '3', '=')
->fieldCondition('realm', 'domain_id', '=')
->fieldCondition('grant_view', '1', '>=')
->range(0,1)
->execute();
Allan Thomas
la source
1
Bien que cela ne puisse pas être fait à la volée dans Drupal 7, cela peut être fait dans Drupal 8 (non publié au moment d'écrire ces lignes). Voir la requête Entity Field a obtenu la prise en charge des jointures pour plus de détails (y compris un exemple).
colan
Dans Drupal 8, toutes les conditions sont comme ça (-> condition ()). Ex d'un EFQ en D8: $ result = \ Drupal :: entityQuery ('node') -> condition ('type', array ('entity_a', 'entity_b'), 'IN') -> condition ('status' , NODE_PUBLISHED) -> condition ('field_myfield.value', '5', '=') -> execute (); Dans Drupal 8 EFQ, la colonne est définie directement dans le champ nom par field_name.value ou field_name.target_id dans drupal 7 is->fieldCondition('field_name', 'target_id', $entities_a, 'IN');
woprrr

Réponses:

30

Vous ne pouvez pas ajouter de jointures supplémentaires à un EntityFieldQuerydirectement (ce n'est pas pris en charge), mais vous pouvez ajouter une balise à la requête, implémenter hook_query_TAG_alter()et ajouter la jointure manuellement lorsque la requête est convertie en une requête db standard.

Ce n'est pas testé, mais vous obtiendrez probablement la plupart du chemin:

$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'node_access')
  // etc
  ->addTag('MYTAG');

// get the query results as normal

Et puis la fonction alter alter:

function MYDMOULE_query_MYTAG_alter(QueryAlterableInterface $query) {
  $query->join('node_access', 'node_access', 'node_access.nid = node.nid');
}

L'autre façon de le faire serait de se sous EntityFieldQuery- classer et d'ajouter la jointure, mais je pense que la méthode ci-dessus est plus simple dans ce cas.

Clive
la source
Existe-t-il une meilleure façon de le faire dans une seule fonction? Même si ce n'est pas le casEntityFieldQuery
Allan Thomas
2
Pas vraiment, la seule autre façon est de construire la requête manuellement en utilisant db_select, alors vous pouvez avoir autant de contrôle que vous le souhaitez
Clive
J'irai avec ça. Thx
Allan Thomas
@Clive ... oh cette réponse est vraiment intéressante. J'aime ça. : P
tenken
2
@Michiel No EntityFieldQueryne fait aucune mise en cache, il s'enroule simplement autour de a SelectQueryet ajoute quelques méthodes pour les entités. Ces méthodes supplémentaires expliquent la légère (très légère) diminution des performances que vous ressentiriez en l'utilisant par opposition à une régulièreSelectQuery
Clive
3

Si vous utilisez des propriétés personnalisées avec vos propres tables, la méthode des balises ne fonctionnera pas. Vous devez utiliser des sous-requêtes à la place:

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'user');

$roles_subquery = db_select('users_roles', 'ur');
$roles_subquery->fields('ur', array('uid'));
$roles_subquery->condition('rid', $my_role_id);

$query->propertyCondition('uid', $roles_subquery, 'IN');

Voir Besoin d'une jointure dans une EntityFieldQuery, que diriez-vous d'une sous-requête? pour plus de détails.

colan
la source
Excellente solution pour des cas comme le mien, avec des tables personnalisées. Super travail!
Ignacio Segura Postigo