Получить всех пользователей с определенными ролями, используя EntityFieldQuery

Я думал, что это непростая задача, но для этого не существует Drupal-метода. Я пришел, насколько знаю, что мне нужно использовать EntityFieldQuery для этого - потому что API сказал условия для user_load_multiple () устарели.

Итак, я пробовал это:

$ query = new EntityFieldQuery;
  $ запрос
    -> entityCondition ('entity_type', 'user')
    - > propertyCondition ( 'избавиться', массив (1,2,3);

  $ result = $ query-> execute ();

Но я получил это:

  

PDOException: SQLSTATE [42S22]: Столбец не найден: 1054 Неизвестный столбец   'users.rid' в 'where clause': SELECT users.uid AS entity_id,   : entity_type AS entity_type, NULL AS revision_id,: bundle AS bundle   FROM {users} пользователей WHERE (users.rid =: db_condition_placeholder_0);   Массив ([: db_condition_placeholder_0] => 3 [: entity_type] => пользователь   [: bundle] => пользователь) в EntityFieldQuery-> execute ()

Итак, я подумал, что мне придется присоединиться к users_roles -Table и т. д., но будет привести к дублированию.

Есть ли у кого-нибудь идея, как это сделать?

34 голоса | спросил Nils Riedemann 13 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 13 Sep 2011 19:22:44 +0400 2011, 19:22:44

11 ответов


29

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

Следует иметь в виду: роли хранятся в другой таблице, чем пользователи. Они добавляются с помощью UserController :: attachLoad .

Кажется, существуют три разных условия, которые вы можете использовать с EntityFieldQuery:

  1. entityCondition (особые условия для объекта: 'entity_type' , 'bundle', 'revision_id' или 'entity_id')
  2. fieldCondition (Условия полей, поддерживаемых полем API)
  3. propertyCondition (Условия для свойств объекта)

Наиболее логичным вариантом (если есть) является использование свойстваCondition, но поскольку роли добавляются пользователю в UserController :: attachLoad Я не думаю, что EntityFieldQuery имеет к нему доступ. Я думаю, что EntityFieldQuery просто использует схему, определенную в hook_schema ().

Это заставляет меня думать, что то, чего вы пытаетесь достичь, невозможно. Обходным решением было бы получить все uids с обычным запросом:

У меня нет доступа к Drupal прямо сейчас, поэтому приведенный ниже код может быть отключен. Я уверен, что кто-то отредактирует ошибки.

//Использовать $ query для чтения
$ query = 'SELECT DISTINCT (ur.uid)
  FROM {users_roles} AS ur
  WHERE ur.rid IN (: rids) ';
$ result = db_query ($ query, array (': rids' => array (1,2,3)));

$ uids = $ result-> fetchCol ();

$ users = user_load_multiple ($ uids);

Если вы сможете достичь того, чего хотите с EntityFieldQuery, я буду просвещен.

ответил Bart 13 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 13 Sep 2011 22:56:53 +0400 2011, 22:56:53
16

На самом деле есть способ сделать это. В своем сердце EntityFieldQuery (EFQ) - это просто запрос к базе данных, который может быть изменен с помощью перехвата запросов.

Самый простой возможный пример:

function mymodule_get_users_by_rolename ($ rolename) {
  $ query = new EntityFieldQuery;
  $ query-> entityCondition ('entity_type', 'user');
  $ Query- > addTag ( 'rolequery');
  $ query-> addMetaData ('rolename', $ rolename);

  return $ query-> execute ();
}

function mymodule_query_rolequery_alter (QueryAlterableInterface $ query) {
  $ rolename = $ query-> getMetaData ('rolename');

  $ role_subquery = db_select ("role", "role");
  $ role_subquery-> условие ('role.name', $ rolename, '=');
  $ role_subquery-> join ('users_roles', "users_to_include", "role.rid = users_to_include.rid");
  $ role_subquery-> поля ('users_to_include', array ('uid' => 'uid'));
  $ role_subquery-> где ('users_to_include.uid = users.uid');
  $ Query- > существует ($ role_subquery);
}

Однако есть несколько небольших предостережений, которые потребуют еще некоторого кодирования. Например, при условии соблюдения единственного условия, присутствующего в EFQ, являющемся условием fieldCondition, базовые значения пользователей не будут присутствовать, поэтому, когда вы выбираете пользователей по ролям и одному условию поля, вам также необходимо убедиться, что таблица пользователей объединяется, а если нет, вручную присоединяйте ее, что немного утомительно.

Но для вашей потребности это будет делать трюк. Понимая, что вы можете вручную изменять запросы EFQ, открывается огромный мир возможностей для создания очень мощных запросов, сохраняя при этом интерфейс чистым и Drupal.

Сообщите мне, есть ли у вас какие-либо вопросы или проблемы.

Изменить: я действительно нашел несколько более эффективный способ сделать это и изменил свой код соответственно.

ответил Tommi Forsström 6 J0000006Europe/Moscow 2013, 19:00:40
16

Он должен сделать трюк

$ query = new EntityFieldQuery;
  $ запрос
    -> entityCondition ('entity_type', 'user')
    - > addTag ( 'role_filter');
  $ results = $ query-> execute ();

/**
* Внедрить hook_query_TAG_alter
*
* @param QueryAlterableInterface $ query
* /
функция MY_MODULE_query_role_filter_alter (QueryAlterableInterface $ query) {
  $ query-> leftJoin ('users_roles', 'r', 'users.uid = r.uid');
  $ и = db_and ()
            -> условие ('r.rid', MY_ROLE_INT, '=');
  $ запрос
    - > условие ($ и);
}
ответил alf 11 PMpFri, 11 Apr 2014 13:33:54 +040033Friday 2014, 13:33:54
6
$ user_list = array ();
$ role = array ('role_1', 'role_2');
$ query = db_select ('users_roles', 'ur');
$ query-> join ('users', 'u', 'u.uid = ur.uid');
$ query-> join ('role', 'r', 'r.rid = ur.rid');
$ Query- > поля ( 'и', массив ( 'UID'));
$ Query- > поля ( 'и', массив ( 'почта'));
$ Query- > поля ( 'и', массив ( 'имя'));

$ query-> условие ('r.name', $ role, 'IN');
$ result = $ query-> execute ();

если ($ результат) {
    foreach ($ result as $ row) {
        $ uid = $ row-> uid;
        $ user_list [$ uid] ['mail'] = $ row-> mail;
        $ user_list [$ uid] ['name'] = $ row-> имя;
        $ user_list [$ uid] ['uid'] = $ uid;
    }
}

return $ user_list;
ответил Dhanesh Haridas 29 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSun, 29 Sep 2013 09:41:18 +0400 2013, 09:41:18
5

Вы все равно можете использовать EntityFieldQuery (), как только вы получите идентификаторы пользователя для своей роли, если хотите, например, потому что вы хотите использовать поле userCondition () или другой метод.

Использование массива $ uids в приведенном выше примере:

$ role = user_role_load_by_name ('my_role_name');
$ result = db_select ('users_roles', 'ur')
-> поля ('ur', array ('uid'))
-> условие ('rid', $ role-> rid)
- > выполнение ();

foreach ($ result as $ record) {
  $ uids [] = $ record-> uid;
}

$ query = new EntityFieldQuery ();
$ query-> entityCondition ('entity_type', 'user')
-> entityCondition ('entity_id', $ uids, 'IN')
- > выполнение ();

Было бы лучше, если бы у EntityFieldQuery был метод объединения.

ответил JUPITER 21 AM00000010000000331 2012, 01:15:03
5

/**
 * Получить пользователей по определенной роли
 * /
function mymodule_get_users_by_role () {
    $ role = user_role_load_by_name ('rolename');
    $ uids = db_select ('users_roles', 'ur')
        -> поля ('ur', array ('uid'))
        -> условие ('ur.rid', $ role-> rid, '=')
        - > выполнить ()
        - > fetchCol ();
    $ users = user_load_multiple ($ uids);
}
ответил ibit 8 FebruaryEurope/MoscowbSat, 08 Feb 2014 23:49:26 +0400000000pmSat, 08 Feb 2014 23:49:26 +040014 2014, 23:49:26
2

Это немного поздно для игры, но я думаю, что это то, о чем просил OP. например нет sql, все drupal. Надеемся, что другие найдут это полезным. Поиск этого привел меня сюда, и вот что я придумал.

/**
     * Пользователи, имеющие роль
     *
     * @param $ role mixed Название или избавление от роли, которую мы хотим, чтобы пользователи имели
     * @param $ active_user boolean Возвращать только активные учетные записи?
     *
     * @return array Массив объектов пользователя с ролью
     * /
    function users_with_role ($ role, $ active_user = TRUE) {
      $ uids = array ();
      $ users = array ();
      if (is_int ($ role)) {
        $ my_rid = $ role;
      }
      else {
        $ role_obj = user_role_load_by_name ($ role);
      }
      $ result = db_select ('users_roles', 'ur')
        - > поля ( 'Ур')
        -> условие ('ur.rid', $ role_obj-> rid, '=')
        - > выполнение ();
      foreach ($ result as $ record) {
        $ uids [] = $ record-> uid;
      };
      $ query = new EntityFieldQuery ();
      $ query-> entityCondition ('entity_type', 'user')
        -> свойствоCondition ('uid', $ uids, 'IN');
      if ($ active_user) {
        $ query-> свойствоCondition ('status', 1);
      }
      $ entities = $ query-> execute ();
      if (! empty ($ entities)) {
        $ users = entity_load ('user', array_keys ($ entities ['user']));
      }
      вернуть $ users;
    }
ответил Gold 19 WedEurope/Moscow2012-12-19T06:22:55+04:00Europe/Moscow12bEurope/MoscowWed, 19 Dec 2012 06:22:55 +0400 2012, 06:22:55
2

OK Это старый, но вы можете сделать что-то вроде этого:

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

$ role_subquery = db_select ('users_roles', 'ur');
$ role_subquery-> fields ('ur', array ('uid'));
$ role_subquery-> условие ('rid', $ my_role_id);

$ query-> свойствоCondition ('uid', $ role_subquery, 'IN');
ответил Fabio Epifani 2 PMpThu, 02 Apr 2015 14:02:48 +030002Thursday 2015, 14:02:48
0

Это действительно более старая тема, и я нашел много хороших подходов.

Я бы немного улучшил решение, предоставленное @alf, потому что я думаю, что один запрос с соединением - лучший подход. Однако мне также нравятся мои функции иметь параметры и не зависеть от константы. Итак, вот оно:

функция MY_MODULE_load_users_by_role ($ rid) {
  $ query = new EntityFieldQuery;
  $ запрос
    -> entityCondition ('entity_type', 'user')
    -> addMetaData ('account_role', user_role_load ($ rid))
    - > addTag ( 'role_filter');
  $ results = $ query-> execute ();

  if (isset ($ results ['user'])) {
    $ uids = array_keys ($ results ['user']);
    $ users = entity_load ('user', $ uids);
  }
  else {
    $ users = array ();
  }

  вернуть $ users;
}

/**
 * Внедрить hook_query_TAG_alter
 *
 * @param QueryAlterableInterface $ query
 * /
функция MY_MODULE_query_role_filter_alter (QueryAlterableInterface $ query) {
  $ rid = $ query-> alterMetaData ['account_role'] -> rid;
  $ query-> leftJoin ('users_roles', 'r', 'users.uid = r.uid');
  $ и = db_and ()
    -> условие ('r.rid', $ rid, '=');
  $ запрос
    - > условие ($ и);
}
ответил benelori 9 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowWed, 09 Sep 2015 17:24:49 +0300 2015, 17:24:49
-1

Вы можете найти хорошие примеры объяснений о том, как использовать EntityFieldQuery здесь:

, но так же, как сказал Бердир, на данный момент «EFQ поддерживает только базовые свойства объекта, которые являются частью таблицы сущностей. Роли пользователя никак не подвержены системе сущностей».

ответил k_zoltan 17 42011vEurope/Moscow11bEurope/MoscowThu, 17 Nov 2011 12:09:27 +0400 2011, 12:09:27
-1

Я не сомневаюсь, что это можно упростить. Это можно сделать, хотя для drupal 8:

//вернуть всех участников "VIP"
$ query = \ Drupal :: entityQuery ('пользователь');
$ nids = $ query-> execute ();
foreach ($ nids как $ nid) {
    $ user = \ Drupal \ user \ Entity \ User :: load ($ nid);
    if ($ user-> hasRole ('VIP'))
        $ emails_VIP_members [] = $ & GT пользователь; getEmail ();
}
 $ Send_to = взрывать ( '', $ emails_VIP_members);
ответил Matoeil 12 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 12 Sep 2016 19:16:56 +0300 2016, 19:16:56

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132