EntityFieldQuery INNER JOIN

21

Я хотел бы выполнить запрос, используя объект EntityFieldQuery. Мне нужно значение из таблицы node и node_access, поэтому мне нужно использовать INNER JOIN. Из документации do я не могу понять, как это возможно.

Вот что у меня есть -

$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();
Аллан Томас
источник
1
Хотя это не может быть сделано на лету в Drupal 7, это может быть сделано в Drupal 8 (не выпущено на момент написания этой статьи). Подробности см. В запросе Entity Field для получения поддержки соединения (включая пример).
колан
В Drupal 8 все условия являются такими (-> условие ()). Пример EFQ в D8: $ result = \ Drupal :: entityQuery ('node') -> условие ('тип', массив ('entity_a', 'entity_b'), 'IN') -> условие ('status') , NODE_PUBLISHED) -> условие ('field_myfield.value', '5', '=') -> execute (); В Drupal 8 EFQ столбец определяется непосредственно в поле имени с помощью field_name.value или field_name.target_id в drupal 7 is->fieldCondition('field_name', 'target_id', $entities_a, 'IN');
woprrr

Ответы:

30

Вы не можете добавлять дополнительные объединения EntityFieldQueryнапрямую (это не поддерживается), но вы можете добавить тег к запросу, внедрить hook_query_TAG_alter()и добавить соединение вручную, когда запрос преобразуется в стандартный запрос БД.

Это не проверено, но, вероятно, поможет вам в этом:

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

// get the query results as normal

А затем запрос изменить функцию:

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

Другой способ сделать это состоит в том, чтобы создать подкласс EntityFieldQueryсамому себе и добавить соединение, но я думаю, что приведенный выше метод проще в этом случае.

Клайв
источник
Есть ли лучший способ сделать это в одной функции? Даже если это не такEntityFieldQuery
Аллан Томас
2
Не совсем, единственный другой способ - это создать запрос вручную с помощью db_select, тогда вы можете иметь столько контроля, сколько захотите
Clive
Я пойду с этим. Спасибо
Аллан Томас
@Clive ... о, этот ответ действительно интересный. Нравится. : P
Tenken
2
@Michiel No EntityFieldQueryне выполняет никакого кэширования, он просто оборачивает SelectQueryи добавляет несколько методов для сущностей. Эти дополнительные методы объясняют небольшое (очень незначительное) снижение производительности, которое вы испытаете, используя его по сравнению с обычнымSelectQuery
Клайв
3

Если вы используете пользовательские свойства со своими таблицами, метод tag не будет работать. Вместо этого вам нужно использовать подзапросы:

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

См. Требуется объединение в EntityFieldQuery, как насчет подзапроса? для деталей.

Колан
источник
Отличное решение для таких случаев, как мой, с пользовательскими таблицами. Потрясающая работа!
Игнасио Сегура Постиго