it-swarm-vi.com

Nhận tất cả người dùng với các vai trò cụ thể bằng EntityFieldQuery

Tôi nghĩ rằng đây là một nhiệm vụ dễ dàng, nhưng dường như không có phương pháp Drupal nào cho việc này. Tôi đã đi xa khi biết rằng tôi phải sử dụng EntityFieldQuery cho việc này - vì API cho biết các điều kiện cho user_load_multiple() không được dùng nữa.

Vì vậy, tôi đã thử điều này:

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

  $result = $query->execute();

Nhưng tôi đã nhận được điều này:

PDOException: SQLSTATE [42S22]: Không tìm thấy cột: 1054 Cột không xác định 'users.rid' trong 'mệnh đề where': SELECT users.uid AS entity_id ,: entity_type AS entity_type, NULL AS revision_id ,: bundle AS bundle TỪ {users} WHERE (users.rid =: db_condition_placeholder_0); Mảng ([: db_condition_placeholder_0] => 3 [: entity_type] => user [: bundle] => user) trong EntityFieldQuery-> exec ()

Vì vậy, suy nghĩ đầu tiên của tôi là, tôi phải tham gia với users_roles- Bảng và cứ thế, nhưng điều đó sẽ dẫn đến trùng lặp.

Có ai có một ý tưởng làm thế nào để làm điều đó?

35
Nils Riedemann

Thành thật mà nói, tôi không có ý tưởng làm thế nào để đạt được điều này. Các ví dụ hay về cách sử dụng EntityFieldQuery rất khó tìm. Vì chưa có ai trả lời câu hỏi này và tôi cũng quan tâm đến giải pháp tôi sẽ cố gắng giúp bạn. Mô tả dưới đây là dự đoán tốt nhất của tôi.

Một điều cần lưu ý: vai trò được lưu trữ trong một bảng khác với người dùng. Chúng được thêm vào bằng cách sử dụng serControll :: AttachLoad .

Dường như có ba điều kiện khác nhau mà bạn có thể sử dụng với EntityFieldQuery:

  1. entityCondition (Điều kiện cụ thể của thực thể: 'entity_type', 'bundle', 'revision_id' hoặc 'entity_id')
  2. fieldCondition (Điều kiện trên các trường được duy trì bởi API trường)
  3. propertyCondition (Điều kiện về thuộc tính thực thể)

Tùy chọn hợp lý nhất (nếu có) sẽ là sử dụng propertyCondition, nhưng khi các vai trò được thêm vào người dùng trong serControll :: AttachLoad Tôi không nghĩ EntityFieldQuery có quyền truy cập vào nó. Tôi nghĩ EntityFieldQuery chỉ sử dụng lược đồ được định nghĩa trong hook_schema ().

Điều này khiến tôi tin rằng những gì bạn đang cố gắng đạt được là không thể. Một cách giải quyết khác là lấy tất cả các uids bằng một truy vấn bình thường:

Tôi không có quyền truy cập vào Drupal ngay bây giờ, vì vậy mã bên dưới có thể bị tắt. Tôi chắc chắn ai đó sẽ chỉnh sửa các lỗi.

// 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);

Nếu có thể đạt được những gì bạn muốn với EntityFieldQuery, tôi sẽ được khai sáng.

32
Bart

Nó sẽ làm các trick

  $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

Thực tế có một cách để làm điều này. Về bản chất, EntityFieldQuery (EFQ) chỉ là một truy vấn cơ sở dữ liệu có thể được thay đổi bằng các móc thay đổi truy vấn.

Ví dụ đơn giản nhất có thể:

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);
}

Tuy nhiên, có một vài cảnh báo nhỏ với điều này sẽ yêu cầu thêm một số mã hóa. Ví dụ: trong việc chăm sóc điều kiện duy nhất có trong EFQ là FieldCondition, cơ sở người dùng sẽ không có mặt, vì vậy khi bạn tìm nạp người dùng theo vai trò và một FieldCondition duy nhất, bạn cũng cần đảm bảo bảng người dùng được tham gia và nếu không, hãy tham gia bằng tay, đây là một quá trình tẻ nhạt.

Nhưng đối với nhu cầu của bạn, điều này sẽ thực hiện các mẹo. Nhận ra bạn có thể thay đổi thủ công các truy vấn EFQ mở ra một thế giới cơ hội lớn để tạo các truy vấn rất mạnh trong khi vẫn giữ giao diện sạch sẽ và Drupal.

Hãy cho tôi biết nếu bạn có bất kỳ câu hỏi hoặc vấn đề.

Chỉnh sửa: Tôi thực sự tìm thấy một cách hiệu quả hơn một chút để làm điều này và thay đổi mã của tôi cho phù hợp.

16
Tommi Forsström
$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

Bạn vẫn có thể sử dụng EntityFieldQuery () sau khi bạn nhận được id người dùng cho vai trò của mình, nếu bạn muốn, ví dụ vì bạn muốn người dùng fieldCondition () hoặc phương thức khác.

Sử dụng mảng $ uids trong ví dụ trên:

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

Sẽ tốt hơn nếu EntityFieldQuery có phương thức nối.

5
JUPITER

OK Đây là một cái cũ, nhưng bạn có thể làm một cái gì đó như thế này:

$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

Đây là một trò chơi hơi muộn, nhưng tôi nghĩ đó là những gì OP yêu cầu. ví dụ. không có sql, tất cả drupal. Hy vọng những người khác sẽ tìm thấy nó hữu ích. Việc tìm kiếm này đã dẫn tôi đến đây và đây là những gì tôi nghĩ ra.

    /**
     * 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

Đây thực sự là một chủ đề cũ hơn và tôi đã tìm thấy rất nhiều cách tiếp cận tốt.

Tôi sẽ cải thiện một chút về giải pháp được cung cấp bởi @alf, vì tôi nghĩ một truy vấn có tham gia là cách tiếp cận tốt nhất. Tuy nhiên tôi cũng thích các hàm của mình có các tham số và không phụ thuộc vào hằng số. Vì vậy, ở đây nó đi:

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