web-gelistirme-sc.com

EntityFieldQuery kullanarak belirli rollere sahip tüm kullanıcıları edinin

Bunun kolay bir görev olduğunu düşündüm, ancak bunun için bir Drupal yöntemi yok gibi görünüyor. API için user_load_multiple() kullanımdan kaldırıldığı için bunun için EntityFieldQuery kullanmam gerektiğini bilerek geldim.

Bu yüzden denedim:

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

  $result = $query->execute();

Yine de bunu aldım:

PDOException: SQLSTATE [42S22]: Sütun bulunamadı: 1054 'where yan tümcesinde' bilinmeyen sütun 'users.rid': SELECT users.uid AS entity_id,: entity_type AS entity_type, NULL AS revision_id,: bundle AS bundle {users} users NEREDE (users.rid =: db_condition_placeholder_0); EntityFieldQuery-> execute () içindeki dizi ([: db_condition_placeholder_0] => 3 [: entity_type] => kullanıcı [: paket] => kullanıcı)

İlk düşüncem, users_roles- Tablo vb. Ancak kopyalara yol açacaktır.

Bunun nasıl yapılacağı hakkında bir fikri olan var mı?

35
Nils Riedemann

Dürüst olmak gerekirse, bunu nasıl başaracağım konusunda hiçbir fikrim yok. EntityFieldQuery kullanımı hakkında iyi örnekler bulmak zordur. Kimse bu soruyu henüz cevaplamadığından ve çözümle de ilgileniyorum. Aşağıda açıklanan en iyi tahminim.

Akılda tutulması gereken bir şey: roller, kullanıcılardan farklı bir tabloda saklanır. Bunlar serController :: attachLoad kullanılarak eklenir.

EntityFieldQuery ile kullanabileceğiniz üç farklı koşul var gibi görünüyor:

  1. entityCondition (Varlığa özgü koşullar: 'entity_type', 'bundle', 'revision_id' veya 'entity_id')
  2. fieldCondition (Alan API'sı tarafından tutulan alanlarla ilgili koşullar)
  3. propertyCondition (Varlık özellikleriyle ilgili koşullar)

En mantıklı seçenek (eğer varsa) bir propertyCondition kullanmak olacaktır, ancak rolleri kullanıcıya serController :: attachLoad olarak eklendiği için EntityFieldQuery buna erişimi olduğunu sanmıyorum. EntityFieldQuery sadece hook_schema () tanımlanan şema kullanır düşünüyorum.

Bu, elde etmeye çalıştığınız şeyin imkansız olduğuna inanmamı sağlıyor. Bir çözüm, tüm sorguları normal bir sorgu ile almak olacaktır:

Drupal şu an için erişimim yok, bu yüzden aşağıdaki kod kapalı olabilir. Eminim birisi hataları düzenleyecektir.

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

EntityFieldQuery ile istediğinizi elde etmek mümkün ise aydınlanacağım.

32
Bart

Hile yapmalı

  $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

Aslında bunu yapmanın bir yolu var. Onun kalbinde, EntityFieldQuery (EFQ) sadece sorgu değiştirme kancaları ile değiştirilebilen bir veritabanı sorgusu.

Olası en basit örnek:

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

Bununla birlikte, biraz daha kodlama gerektiren birkaç küçük uyarı vardır. Örneğin, EFQ'da bir fieldCondition olan tek koşulun bakımı durumunda, kullanıcı tabanlısı mevcut olmayacaktır, bu nedenle kullanıcıları role ve tek bir fieldCondition'a getirdiğinizde, Kullanıcılar tablosu birleştirilir ve değilse, biraz sıkıcı bir süreç olan manuel olarak katılın.

Ama ihtiyacın için, bu hile yapacak. EFQ sorgularını manuel olarak değiştirebileceğinizi fark etmek, arabirimi temiz ve Drupal'ı korurken çok güçlü sorgular oluşturmak için büyük bir fırsatlar dünyası açar.

Herhangi bir sorunuz veya sorununuz varsa bize bildirin.

Düzenleme: Aslında bunu yapmak için biraz daha performanslı bir yol buldum ve buna göre kodumu değiştirdim.

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

Rolünüz için kullanıcı kimliklerini aldıktan sonra, örneğin fieldCondition () kullanıcısını veya başka bir yöntemi kullanmak istediğiniz için, EntityFieldQuery () yöntemini kullanabilirsiniz.

Yukarıdaki örnekte $ uids dizisini kullanma:

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

EntityFieldQuery bir join yöntemi olsaydı daha güzel olurdu.

5
JUPITER

Tamam Bu eskidir, ancak böyle bir şey yapabilirsiniz:

$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

Bu oyuna biraz geç kaldı, ama bence OP'nin istediği buydu. Örneğin. sql yok, hepsi drupal. Umarım başkaları bunu faydalı bulur. Bunun arayışı beni buraya getirdi ve ben de bunu buldum.

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

Bu gerçekten daha eski bir konu ve birçok iyi yaklaşım buldum.

Ben birleştirme ile bir sorgu en iyi yaklaşım olduğunu düşünüyorum, çünkü @ alf tarafından sağlanan çözüm üzerinde biraz geliştirmek. Ancak fonksiyonumun parametrelere sahip olmasını ve sabit kalmamasını da seviyorum. İşte böyle:

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