EntityFieldQuery का उपयोग करके विशिष्ट भूमिकाओं वाले सभी उपयोगकर्ताओं को प्राप्त करें


35

मुझे लगा कि यह एक आसान काम है, फिर भी इसके लिए एक ड्रुपल-विधि नहीं लगती है। मुझे यह पता चला कि मुझे इसके लिए उपयोग EntityFieldQueryकरना है - क्योंकि एपीआई ने कहा है कि शर्तों user_load_multiple()को हटा दिया गया है।

इसलिए मैंने यह कोशिश की:

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

  $result = $query->execute();

फिर भी मुझे यह मिल गया:

PDOException: SQLSTATE [42S22]: कॉलम नहीं मिला: 1054 अज्ञात कॉलम 'users.rid' में 'जहां क्लॉज': SELECT users.uid AS यूनिट_id,: unit_type AS unit_type, NULL AS revision_id: बंडल बंडल फ्रॉम {यूजर्स} WHERE (users.rid =: db_condition_placeholder_0); सरणी ([: db_condition_placeholder_0] => 3 [: Unit_type] => उपयोगकर्ता [: बंडल] => उपयोगकर्ता) EntityFieldQuery-> निष्पादित () में

तो मेरा पहला विचार था, मैं के साथ शामिल होने के लिए होगा कि users_roles-Table और इतने पर है, लेकिन यह होगा डुप्लिकेट के लिए सीसा।

किसी को भी यह कैसे करना है एक विचार है?


user_load_multiple () भी एक नहीं है। उम्मीद है कि हमारे पास डी 8 में ऐसा करने का एक तरीका होगा।
दलीन

आप मेरे EntityFieldQueryExtra सैंडबॉक्स का उपयोग कर सकते हैं क्योंकि यह अनुमति देता है ->propertyCondition('rid', array(1, 2, 3));
mikeytown2

जवाबों:


32

सच कहूं, तो मुझे नहीं पता कि इसे कैसे हासिल किया जाए। EntityFieldQuery का उपयोग कैसे करें के अच्छे उदाहरण खोजना मुश्किल है। चूंकि किसी ने भी इस सवाल का जवाब नहीं दिया है और मैं भी इस समाधान में दिलचस्पी रखता हूँ, इसलिए मैं आपकी मदद करने की कोशिश करूँगा। नीचे वर्णित मेरा सबसे अच्छा अनुमान है।

ध्यान रखने वाली बात: भूमिकाएं उपयोगकर्ताओं की तुलना में एक अलग तालिका में संग्रहीत की जाती हैं। उन्हें UserController :: संलग्नक का उपयोग करके जोड़ा जाता है

ऐसी तीन अलग-अलग स्थितियाँ हैं जिनका आप EntityFieldQuery के साथ उपयोग कर सकते हैं:

  1. एंटीकॉन्डिशन (इकाई विशिष्ट शर्तें: 'एंट्री_टाइप', 'बंडल', vision रिवीज़न_आईडी ’या) एंट्री_आईडी’)
  2. फ़ील्डकंडिशन (फ़ील्ड API द्वारा अनुरक्षित फ़ील्ड पर स्थितियां)
  3. प्रॉपर्टीकंडिशन (एंटिटी प्रॉपर्टीज पर स्थितियां)

सबसे तार्किक विकल्प (अगर वहाँ एक है) एक प्रॉपर्टीकंडिशन का उपयोग करना होगा, लेकिन उपयोगकर्ता के रूप में भूमिकाओं को उपयोगकर्ताकंट्रोलर में जोड़ा जाता है :: संलग्नक मुझे नहीं लगता कि EntityFieldQuery की इसके पास पहुंच है। मुझे लगता है कि EntityFieldQuery सिर्फ hook_schema () में परिभाषित स्कीमा का उपयोग करता है।

यह मुझे विश्वास दिलाता है कि आप जो हासिल करना चाहते हैं वह असंभव है। एक सामान्य प्रश्न के साथ सभी uids प्राप्त करने के लिए एक वर्कअराउंड होगा:

अभी मेरे पास Drupal तक पहुंच नहीं है, इसलिए नीचे दिया गया कोड बंद हो सकता है। मुझे यकीन है कि कोई व्यक्ति गलतियों को संपादित करेगा।

// 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 के साथ जो चाहते हैं उसे हासिल करना संभव है, तो मैं प्रबुद्ध हो जाऊंगा।


1
हाँ, इस तरह से मैं चला गया। फिर भी मैं बहुत उत्सुक हूं कि ईएफक्यू के साथ इसे कैसे हासिल किया जाए और इस सवाल को खुला छोड़ देंगे। यह एक ख़ुशी की बात है कि EFQs अभी तक अच्छी तरह से प्रलेखित नहीं हुए हैं क्योंकि वे लंबे समय में मेरे लिए दृश्य बदल सकते हैं।
नेल्स रिडमैन

ईएफक्यू केवल एक इकाई के मूल गुणों का समर्थन करता है, जो इकाई तालिका का हिस्सा हैं। किसी उपयोगकर्ता की भूमिका इकाई प्रणाली के लिए किसी भी तरह से उजागर नहीं होती है।
बेर्डिर

1
इसके अलावा, अनुकूलन संकेत: आप $ uids initalization और foreach को बदल सकते हैं $uids = $result->fetchColumn()
बेर्दिर

बेर्डिर कोड को संपादित करने के लिए स्वतंत्र महसूस करें :)
बार्ट

19

यह चाल करना चाहिए

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

मुझे आश्चर्य है कि इस जवाब में इतने कम वोट क्यों हैं। यह सबसे अच्छा उपाय है। हालांकि मुझे ध्यान देना चाहिए कि $query->leftJoin('users_roles', 'r', 'users.uid = r.uid');अज्ञात कॉलम 'यूआईडी' का कारण बन सकता है। उस स्थिति में हमें जोड़ने की आवश्यकता है $query->propertyCondition('uid', 0, '!='), इसलिए उपयोगकर्ता तालिका क्वेरी में होगी।
एलमन

1
निश्चित रूप से यह स्वीकृत उत्तर होना चाहिए।
फ्रैंक रॉबर्ट एंडरसन

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

हालांकि इसके साथ कुछ छोटे कैविएट हैं जिन्हें कुछ और कोडिंग की आवश्यकता होगी। उदाहरण के लिए EFQ में मौजूद एकमात्र शर्त की देखभाल में एक फील्डकंडिशन के रूप में, यूजर्स-बेसिटेबल मौजूद नहीं होंगे, इसलिए जब आप यूजर्स को रोल और सिंगल फील्ड कॉन्डिशन के लिए ला रहे हैं, तो आपको यह भी सुनिश्चित करना होगा! उपयोगकर्ता तालिका में शामिल हो गए हैं और यदि नहीं, तो मैन्युअल रूप से इसमें शामिल हों, जो एक थकाऊ प्रक्रिया है।

लेकिन आपकी जरूरत के लिए, यह चाल चलेगा। एहसास आप मैन्युअल रूप से बदल सकते हैं EFQ प्रश्नों इंटरफ़ेस साफ और Drupal रखते हुए बहुत शक्तिशाली प्रश्न बनाने के लिए अवसरों की एक विशाल दुनिया को खोलता है।

यदि आपके कोई प्रश्न या मुद्दे हैं, तो मुझे बताएं।

संपादित करें: मुझे वास्तव में ऐसा करने का थोड़ा और अच्छा तरीका मिला और मैंने अपने कोड को तदनुसार बदल दिया।


आधारभूत आवश्यकता को "हैक" करने का एक तरीका हमेशा $ क्वेरी-> प्रॉपर्टीकंडिशन ('यूआईडी', 0, '! =') जैसे फर्जी संपत्ति को जोड़ना है; क्वेरी के लिए। यह आधार से जुड़े होने के लिए मजबूर करता है, लेकिन ईएफक्यू एक एकल फ़ील्डकंडिशन के मामले में आधार को छोड़ देता है, क्योंकि बस डेटा फ़ील्ड को क्वेरी करने के लिए तेज़ तरीका है, क्योंकि ईएफक्यू एक बिट के कारण प्रदर्शन में बाधा डालता है।
टॉमी फोर्सस्ट्रम

2
मुझे नहीं लगता कि यह सबसे सरल संभव उदाहरण है, जैसा कि दावा किया गया है। क्या आप दो जोड़ों के पक्ष में और एक शर्त पर सीधे उपकेंद्र को नहीं खोद सकते $query? और मैं mymodule_get_users_by_rolenameखुद को क्वेरी के परिणाम को वापस नहीं करने के लिए बदलने के लिए सुझाव दे सकता हूं , लेकिन कुंजी को हटाने के लिए 'user'
पीटर टेलर

6
$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;

5

आप अपनी भूमिका के लिए उपयोगकर्ता आईडी प्राप्त करने के बाद भी यदि आप चाहते हैं, तो आप EntityFieldQuery () का उपयोग कर सकते हैं, उदाहरण के लिए, क्योंकि आप उपयोगकर्ता फ़ील्डकंडिशन () या किसी अन्य विधि से चाहते हैं।

उपरोक्त उदाहरण में $ uids सरणी का उपयोग करना:

$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 में एक विधि शामिल हो।


1
यदि आपके पास इस भूमिका के साथ कुछ दर्जन से अधिक उपयोगकर्ता हैं, तो इस EFQ में भयानक प्रदर्शन होगा।
दलिन

5

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

मुझे लगता है कि यह शायद सबसे कुशल जवाब है। एक मामूली सुधार के रूप में मैं एक पैरामीटर जोड़ूंगा $rolenameजिसका उपयोग कॉल में किया जाएगा user_role_load_by_nameऔर यह सुनिश्चित करने के लिए एक चेक user_role_load_by_nameझूठी वापस नहीं आएगा।
स्टेफगोसेलिन

4

ठीक है यह एक पुराना है, लेकिन आप ऐसा कुछ कर सकते हैं:

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

मैंने अपना दिमाग बदल दिया यह सबसे अच्छा जवाब है। को छोड़कर, आप एक अर्ध-उपनिवेश याद कर रहे हैं और $ my_role_id अपरिभाषित है।
फ्रैंक रॉबर्ट एंडरसन

2

इस खेल में थोड़ी देर हो गई है, लेकिन मुझे लगता है कि यह वही है जो ओपी पूछ रहा था। उदाहरण के लिए कोई sql, सभी drupal। उम्मीद है कि अन्य इसे उपयोगी पाएंगे। इस खोज ने मुझे यहां तक ​​पहुंचाया और यही मैं साथ आया।

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

यदि आपके पास इस भूमिका के साथ कुछ दर्जन से अधिक उपयोगकर्ता हैं, तो इस EFQ में भयानक प्रदर्शन होगा।
दलिन

@ डेलिन, प्रारंभिक योग्यता, (अर्थात कोई वर्ग, सभी ड्रुपल) को देखते हुए, आप एक विधि के रूप में क्या सुझाव देंगे जिससे बेहतर प्रदर्शन प्राप्त होगा?
गोल्ड

1
हे स्वर्ण! ऐसा लगता है कि db_select () स्थिति से $ भूमिका एक स्ट्रिंग होने की उम्मीद है, और यदि आप एक पूर्णांक में पास होते हैं तो यह $ रोल पर पकड़ा जाएगा_बजट सेट नहीं किया जा रहा है जब यह $ भूमिका_बज-> से छुटकारा दिलाता है। संपादित करें: मैं उत्तर संपादित कर सकता हूं, वू।
क्रिस बर्गेस

0

यह वास्तव में एक पुराना विषय है और मुझे बहुत सारे अच्छे दृष्टिकोण मिले।

मैं @alf द्वारा प्रदान किए गए समाधान पर थोड़ा सुधार करूंगा, क्योंकि मुझे लगता है कि जुड़ने के साथ एक क्वेरी सबसे अच्छा तरीका है। हालाँकि मुझे अपने कार्य भी पैरामीटर पसंद हैं और न कि एक स्थिर पर निर्भर। तो यहाँ यह जाता है:

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

-1

आप यहाँ EntityFieldQuery का उपयोग कैसे करें के बारे में एक अच्छा स्पष्टीकरण उदाहरण पा सकते हैं:

  • http://drupal.org/node/1343708 (इस लेख में आपको अधिक उपयोगी संसाधन, ट्यूटोरियल और उदाहरण मिलेंगे)

लेकिन अभी तक के रूप में के रूप में Berdir ने कहा "EFQ केवल एक इकाई के मूल गुणों का समर्थन करता है, जो इकाई तालिका का हिस्सा हैं। उपयोगकर्ता की भूमिकाएं इकाई प्रणाली के लिए किसी भी तरह से उजागर नहीं होती हैं।"


-2

मुझे इसमें कोई संदेह नहीं है कि इसे सरल बनाया जा सकता है। यह हालांकि ड्रुपल 8 के लिए किया जा सकता है:

//retrieve all "VIP" members
$query = \Drupal::entityQuery('user');
$nids = $query->execute();
foreach ($nids as $nid){
    $user = \Drupal\user\Entity\User::load($nid);
    if ($user->hasRole('VIP'))
        $emails_VIP_members[]=$user->getEmail();
}
 $send_to=implode(',',$emails_VIP_members);

उपयोगकर्ता मेल को इकट्ठा करने के लिए सीधे क्वेरी का उपयोग करने के लिए बेहतर है, बजाय सभी को लोड करने के
कोडोड

उन जवाबों में से एक में यह समाधान है?
Matoeil
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.