it-swarm.com.de

Holen Sie sich alle Benutzer mit bestimmten Rollen mit EntityFieldQuery

Ich dachte, dies sei eine leichte Aufgabe, aber es scheint keine Drupal-Methode dafür zu geben. Ich bin so weit gekommen zu wissen, dass ich EntityFieldQuery dafür verwenden muss - weil die API die Bedingungen für user_load_multiple() als veraltet bezeichnet.

Also habe ich das versucht:

  $query = new EntityFieldQuery;
  $query
    ->entityCondition('entity_type', 'user')
    ->propertyCondition('rid',array(1,2,3);

  $result = $query->execute();

Trotzdem habe ich folgendes verstanden:

PDOException: SQLSTATE [42S22]: Spalte nicht gefunden: 1054 Unbekannte Spalte 'users.rid' in 'where-Klausel': SELECT users.uid AS entity_id ,: entity_type AS entity_type, NULL AS revision_id ,: Bündel AS bundle FROM {users} Benutzer WHERE (users.rid =: db_condition_placeholder_0); Array ([: db_condition_placeholder_0] => 3 [: entity_type] => user [: bundle] => user) in EntityFieldQuery-> execute ()

Mein erster Gedanke war also, dass ich mich mit users_roles - Table usw. verbinden müsste, aber dass zu Duplikaten führen würde .

Hat jemand eine Idee, wie es geht?

35
Nils Riedemann

Um ehrlich zu sein, habe ich keine Ahnung, wie ich das erreichen kann. Gute Beispiele für die Verwendung von EntityFieldQuery sind schwer zu finden. Da diese Frage noch niemand beantwortet hat und ich auch an der Lösung interessiert bin, werde ich versuchen, Ihnen zu helfen. Unten beschrieben ist meine beste Vermutung.

Beachten Sie Folgendes: Rollen werden in einer anderen Tabelle als Benutzer gespeichert. Sie werden mit serController :: attachLoad hinzugefügt.

Es scheint drei verschiedene Bedingungen zu geben, die Sie mit einer EntityFieldQuery verwenden können:

  1. entityCondition (Entitätsspezifische Bedingungen: 'entity_type', 'bundle', 'revision_id' oder 'entity_id')
  2. fieldCondition (Bedingungen für Felder, die von der Feld-API verwaltet werden)
  3. propertyCondition (Bedingungen für Entitätseigenschaften)

Die logischste Option (falls vorhanden) wäre die Verwendung einer propertyCondition, aber wenn dem Benutzer Rollen hinzugefügt werden in serController :: attachLoad Ich glaube nicht, dass die EntityFieldQuery Zugriff darauf hat. Ich denke, die EntityFieldQuery verwendet nur das in hook_schema () definierte Schema.

Dies lässt mich glauben, dass das, was Sie erreichen wollen, unmöglich ist. Eine Problemumgehung wäre, alle Uids mit einer normalen Abfrage abzurufen:

Ich habe momentan keinen Zugriff auf Drupal, daher ist der folgende Code möglicherweise deaktiviert. Ich bin sicher, dass jemand die Fehler bearbeiten wird.

// Use $query for readability
$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);

Wenn es möglich ist, mit EntityFieldQuery das zu erreichen, was Sie wollen, werde ich aufgeklärt.

32
Bart

Es sollte den Trick machen

  $query = new EntityFieldQuery;
  $query
    ->entityCondition('entity_type', 'user')
    ->addTag('role_filter');
  $results = $query->execute();

/**
* Implement hook_query_TAG_alter
* 
* @param QueryAlterableInterface $query
*/
function MY_MODULE_query_role_filter_alter(QueryAlterableInterface $query) {
  $query->leftJoin('users_roles', 'r', 'users.uid = r.uid');  
  $and = db_and()
            ->condition('r.rid', MY_ROLE_INT, '=');
  $query
    ->condition($and);
}
19
alf

Es gibt tatsächlich einen Weg, dies zu tun. Die EntityFieldQuery (EFQ) ist in ihrem Herzen nur eine Datenbankabfrage, die mit Abfrageänderungs-Hooks geändert werden kann.

Einfachstes mögliches Beispiel:

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->condition('role.name', $rolename, '=');
  $role_subquery->join('users_roles', "users_to_include", "role.rid = users_to_include.rid");
  $role_subquery->fields('users_to_include', array('uid' => 'uid'));
  $role_subquery->where('users_to_include.uid = users.uid');
  $query->exists($role_subquery);
}

Es gibt jedoch ein paar kleine Einschränkungen, die etwas mehr Codierung erfordern würden. Wenn beispielsweise die einzige in der EFQ vorhandene Bedingung eine Feldbedingung ist, ist die Benutzer-Basetabelle nicht vorhanden. Wenn Sie also Benutzer nach Rolle und einer einzelnen Feldbedingung abrufen, müssen Sie auch sicherstellen, dass die Die Benutzertabelle wird verbunden, und wenn nicht, wird sie manuell verbunden, was ein etwas langwieriger Prozess ist.

Aber für Ihre Bedürfnisse wird dies den Trick tun. Die Erkenntnis, dass Sie EFQ-Abfragen manuell ändern können, eröffnet eine Vielzahl von Möglichkeiten, sehr leistungsstarke Abfragen zu erstellen und gleichzeitig die Benutzeroberfläche sauber und Drupal zu halten.

Lassen Sie mich wissen, wenn Sie Fragen oder Probleme haben.

Bearbeiten: Ich habe tatsächlich einen etwas performanteren Weg gefunden und meinen Code entsprechend geändert.

16
$user_list = array();
$roles = 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->fields('u',array('uid'));
$query->fields('u',array('mail'));
$query->fields('u',array('name'));

$query->condition('r.name', $roles, 'IN');
$result = $query->execute();

if($result){
    foreach($result as $row ) {
        $uid = $row->uid;
        $user_list[$uid]['mail'] = $row->mail;
        $user_list[$uid]['name'] = $row->name;
        $user_list[$uid]['uid'] = $uid;
    }
}

return $user_list;
6
Dhanesh Haridas

/**
 * Get users by specific role
 */
function mymodule_get_users_by_role() {
    $role = user_role_load_by_name('rolename');
    $uids = db_select('users_roles', 'ur')
        ->fields('ur', array('uid'))
        ->condition('ur.rid', $role->rid, '=')
        ->execute()
        ->fetchCol();
    $users = user_load_multiple($uids);
}
5
ibit

Sie können EntityFieldQuery () weiterhin verwenden, sobald Sie die Benutzer-IDs für Ihre Rolle erhalten haben, wenn Sie dies möchten, z. B. weil Sie fieldCondition () oder eine andere Methode verwenden möchten.

Verwenden des Arrays $ uids im obigen Beispiel:

$role = user_role_load_by_name('my_role_name');
$result = db_select('users_roles', 'ur')
->fields('ur', array('uid'))
->condition('rid', $role->rid)
->execute();

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

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'user')
->entityCondition('entity_id', $uids, 'IN')
->execute();

Es wäre schöner, wenn EntityFieldQuery eine Join-Methode hätte.

5
JUPITER

OK Dies ist eine alte, aber Sie könnten so etwas tun:

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

Das ist etwas spät im Spiel, aber ich denke, es ist das, wonach das OP gefragt hat. z.B. kein sql, alles drupal. Hoffentlich finden es andere nützlich. Die Suche danach hat mich hierher geführt und das habe ich mir ausgedacht.

    /**
     * Users with role
     *
     * @param $role mixed The name or rid of the role we're wanting users to have
     * @param $active_user boolean Only return active accounts?
     *
     * @return array An array of user objects with the role
     */
    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')
        ->fields('ur')
        ->condition('ur.rid', $role_obj->rid, '=')
        ->execute();
      foreach ($result as $record) {
        $uids[] = $record->uid;
      };
      $query = new EntityFieldQuery();
      $query->entityCondition('entity_type', 'user')
        ->propertyCondition('uid', $uids, 'IN');
      if ($active_user) {
        $query->propertyCondition('status', 1);
      }
      $entities = $query->execute();
      if (!empty($entities)) {
        $users = entity_load('user', array_keys($entities['user']));
      }
      return $users;
    }
2
Gold

Dies ist in der Tat ein älteres Thema und ich habe viele gute Ansätze gefunden.

Ich würde die von @alf bereitgestellte Lösung etwas verbessern, da ich denke, dass eine Abfrage mit Join der beste Ansatz ist. Ich mag es aber auch, wenn meine Funktionen Parameter haben und nicht von einer Konstanten abhängen. Also los geht's:

function MY_MODULE_load_users_by_role($rid) {
  $query = new EntityFieldQuery;
  $query
    ->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();
  }

  return $users;
}

/**
 * Implement hook_query_TAG_alter
 *
 * @param QueryAlterableInterface $query
 */
function MY_MODULE_query_role_filter_alter(QueryAlterableInterface $query) {
  $rid = $query->alterMetaData['account_role']->rid;
  $query->leftJoin('users_roles', 'r', 'users.uid = r.uid');
  $and = db_and()
    ->condition('r.rid', $rid, '=');
  $query
    ->condition($and);
}
0
benelori