EntityFieldQuery INNER JOIN

21

Chciałbym uruchomić zapytanie przy użyciu obiektu EntityFieldQuery. Potrzebuję wartości zarówno z tabeli node, jak i node_access, dlatego musiałbym użyć INNER JOIN. Z dokumentacji do nie mogę dowiedzieć się, jak to możliwe.

Oto co mam -

$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
źródło
1
Chociaż nie można tego zrobić w locie w Drupal 7, można to zrobić w Drupal 8 (niepublikowane w momencie pisania tego tekstu). Zobacz Zapytanie Entity Field uzyskało wsparcie dołączania, aby uzyskać szczegółowe informacje (w tym przykład).
colan
W Drupal 8 wszystkie warunki są takie (-> warunek ()). Przykład EFQ w D8: $ result = \ Drupal :: entityQuery ('node') -> condition ('type', array ('entity_a', 'entity_b'), 'IN') -> condition ('status' , NODE_PUBLISHED) -> warunek ('field_myfield.value', '5', '=') -> execute (); W Drupal 8 EFQ kolumna jest zdefiniowana bezpośrednio w polu nazwy przez ->fieldCondition('field_name', 'target_id', $entities_a, 'IN');
nazwa_pola. Wartość lub nazwa_pola. Identyfikator_docelowy

Odpowiedzi:

30

Nie możesz dodać dodatkowych złączeń EntityFieldQuerybezpośrednio (nie jest to obsługiwane), ale możesz dodać znacznik do zapytania, zaimplementować hook_query_TAG_alter()i dodać złączenie ręcznie, gdy zapytanie zostanie przekształcone w standardowe zapytanie db.

Nie jest to testowane, ale prawdopodobnie zapewni Ci większość możliwości:

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

// get the query results as normal

A potem funkcja zmiany zapytania:

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

Innym sposobem na zrobienie tego byłoby podklasowanie EntityFieldQueryi dodanie sprzężenia, ale myślę, że powyższa metoda jest w tym przypadku prostsza.

Clive
źródło
Czy jest lepszy sposób, aby to zrobić za pomocą jednej funkcji? Nawet jeśli nie jestEntityFieldQuery
Allan Thomas,
2
Nie bardzo, jedynym innym sposobem jest ręczne utworzenie zapytania, dzięki db_selectczemu możesz mieć nad nim pełną kontrolę
Clive
Pójdę z tym. Dzięki
Allan Thomas,
@Clive ... och, ta odpowiedź jest naprawdę interesująca. Lubię to. : P
tenken,
2
@Michiel No EntityFieldQuerynie buforuje , po prostu owija się wokół SelectQueryi dodaje pewne metody dla encji. Te dodatkowe metody odpowiadają za niewielki (bardzo niewielki) spadek wydajności, którego doświadczyłbyś podczas korzystania z niego w przeciwieństwie do zwykłegoSelectQuery
Clive
3

Jeśli używasz niestandardowych właściwości z własnymi tabelami, metoda tagu nie będzie działać. Zamiast tego musisz użyć podkwerend:

$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');

Zobacz Potrzebujesz dołączyć do EntityFieldQuery, a co z podzapytaniem? dla szczegółów.

colan
źródło
Doskonałe rozwiązanie dla skrzynek takich jak mój, z niestandardowymi tabelami. Świetna robota!
Ignacio Segura Postigo,