এন্টিফিল্ডকিউরি ব্যবহার করে নির্দিষ্ট ভূমিকা সহ সমস্ত ব্যবহারকারীকে পান


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 অজানা কলাম 'ব্যবহারকারীর.কর্ম' যেখানে 'ক্লজ': ব্যবহারকারীদের নির্বাচন করুন; সত্তা_আইএসপি হিসাবে: এনটিটি-টাইপ হিসাবে সত্তা_প্রকার, নূন্য হিসাবে সংশোধন_আইডি: ব্যবহারকারীদের থেকে বান্ডেল হিসাবে ব্যবহারকারী nd ব্যবহারকারী যেখানে (users.rid =: db_condition_ placeholder_0); সত্ত্বা ([: db_condition_ placeholder_0] => 3 [: সত্তা_প্রকার] => ব্যবহারকারী [: বান্ডেল] => ব্যবহারকারী) এন্টিফিল্ডকিয়ারিতে>> এক্সিকিউট করুন ()

সুতরাং আমার প্রথম চিন্তা ছিল, আমাকে- users_rolesটেবিল এবং এর সাথে যোগ দিতে হবে তবে এটি নকলগুলি নিয়ে যাবে।

এটি কীভাবে করা যায় কারও কি ধারণা আছে?


ব্যবহারকারীর_লোড_মুক্তি ()ও কোনও অগ্রগামী। আশা করি আমরা ডি 8-তে এটি করার একটি উপায় পেয়ে যাব।
ডালিন

আপনি আমার এন্টিফিল্ডকিউরিএক্সট্রা স্যান্ডবক্সটিকে এটির অনুমতি দেয় হিসাবে ব্যবহার করতে পারেন ->propertyCondition('rid', array(1, 2, 3));
মাইকাইটাউন

উত্তর:


32

সত্যি কথা বলতে কী কীভাবে এটি অর্জন করা যায় সে সম্পর্কে আমার কোনও ধারণা নেই। কীভাবে এন্টিফিল্ডকুয়েরি ব্যবহার করবেন তার ভাল উদাহরণ পাওয়া শক্ত hard যেহেতু নুন এখনও এই প্রশ্নের উত্তর দিয়েছেন এবং আমি সমাধানে আগ্রহী আমি আপনাকে সাহায্য করার চেষ্টা করব। নীচে বর্ণিত আমার সেরা অনুমান।

একটি বিষয় মনে রাখতে হবে: ভূমিকাগুলি ব্যবহারকারীদের তুলনায় আলাদা টেবিলে সংরক্ষণ করা হয়। এগুলি ইউজারকন্ট্রোলার :: সংযুক্তি লোড ব্যবহার করে যুক্ত করা হয় ।

এখানে তিনটি পৃথক শর্ত রয়েছে যা আপনি একটি এন্টিফিল্ডকিউরির সাথে ব্যবহার করতে পারেন:

  1. প্রতিষ্ঠানের শর্ত ( সত্তার নির্দিষ্ট শর্তাদি: 'সত্তা_প্রকার', 'বান্ডিল', 'রিভিশন_আইডি' বা 'সত্তা_আইডি')
  2. ফিল্ডকন্ডিশন (ফিল্ড এপিআই দ্বারা পরিচালিত ক্ষেত্রগুলির শর্তাদি)
  3. প্রপার্টি কন্ডিশন (সত্তার সম্পত্তি সম্পর্কিত শর্ত)

সর্বাধিক যৌক্তিক বিকল্পটি (যদি সেখানে থাকে) হ'ল একটি সম্পত্তিকন্ডিশন ব্যবহার করা হবে, তবে ইউজারকন্ট্রোলার ব্যবহারকারীর ভূমিকা যেমন যুক্ত করা হয়েছে :: সংযুক্তি লোড আমি মনে করি না যে এনটিটিফিল্ডকোয়ারিতে এর অ্যাক্সেস রয়েছে। আমি মনে করি এন্টিফিল্ডকিউয়ারি হুক_স্কেমার () এ সংজ্ঞায়িত স্কিমাটি কেবলমাত্র ব্যবহার করে।

এটি আমাকে বিশ্বাস করতে পরিচালিত করে যে আপনি যা অর্জন করার চেষ্টা করছেন তা অসম্ভব। একটি সাধারণ জিজ্ঞাসা সহ সমস্ত uids পেতে একটি কর্মপরিকল্পনা হবে:

আমার এখনই ড্রুপলের অ্যাক্সেস নেই, সুতরাং নীচের কোডটি বন্ধ হতে পারে। আমি নিশ্চিত কেউ ভুলগুলি সম্পাদনা করবেন।

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

আপনি যদি ইন্টিফিল্ডকিউয়ের সাথে যা চান তা অর্জন করা সম্ভব হয়, তবে আমি আলোকিত হব।


1
হ্যাঁ, আমি এভাবেই চলেছি। তবুও আমি খুব আগ্রহী যে কীভাবে এএফকিউ দিয়ে এটি অর্জন করব এবং প্রশ্নটি খোলা রাখবে। এটি অত্যন্ত দুঃখের বিষয় যে EFQ গুলি এখনও সেভাবে ডকুমেন্টেড হয় নি কারণ তারা দীর্ঘমেয়াদে আমার জন্য দর্শনগুলি পুরোপুরি প্রতিস্থাপন করতে পারে।
নিলস রিডিম্যান

EFQ কেবল সত্তার প্রাথমিক বৈশিষ্ট্যগুলিকে সমর্থন করে যা সত্তা সারণির অংশ। কোনও ব্যবহারকারীর ভূমিকা সত্তা সিস্টেমে কোনওভাবেই প্রকাশিত হয় না।
বার্ডির

1
এছাড়াও, অপ্টিমাইজেশনের ইঙ্গিত: আপনি ids uids ইনালিটালাইজেশন এবং পূর্বাভাস এর সাথে প্রতিস্থাপন করতে পারেন $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');এটি অজানা কলাম 'uid' হতে পারে। $query->propertyCondition('uid', 0, '!=')সেক্ষেত্রে আমাদের যুক্ত করা দরকার , সুতরাং ব্যবহারকারীদের সারণীটি ক্যোয়ারিতে থাকবে।
এলামান

1
অবশ্যই এটি গ্রহণযোগ্য উত্তর হওয়া উচিত।
ফ্রাঙ্ক রবার্ট অ্যান্ডারসন

16

এটি করার একটি উপায় আসলে আছে। এর হৃদয়ে, এন্টিফিল্ডকিউরি (ইএফকিউ) কেবলমাত্র একটি ডাটাবেস ক্যোয়ারী যা ক্যোয়ারী অল্টার হুকের সাহায্যে পরিবর্তন করা যেতে পারে।

সহজতম উদাহরণ:

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

তবে এর সাথে কয়েকটি ছোট ক্যাভেট রয়েছে যার জন্য আরও কিছু কোডিং লাগবে require উদাহরণস্বরূপ, EFQ- র ক্ষেত্র শর্ত হিসাবে উপস্থিত একমাত্র শর্তের যত্নের ক্ষেত্রে ব্যবহারকারী-ভিত্তিযোগ্য উপস্থিত থাকবে না, সুতরাং যখন আপনি ভূমিকা এবং একটি একক ক্ষেত্রশর্ত দ্বারা ব্যবহারকারীদের আনছেন, তখন আপনাকে অবশ্যই এটি নিশ্চিত করতে হবে ব্যবহারকারীর টেবিলটি যুক্ত হয়েছে এবং যদি তা না হয় তবে ম্যানুয়ালি এটিতে যোগ দিন, যা কিছুটা ক্লান্তিকর প্রক্রিয়া।

তবে আপনার প্রয়োজনের জন্য, এটি কৌশলটি করবে। আপনি নিজেই EFQ ক্যোয়ারী পরিবর্তন করতে পারবেন তা উপলব্ধি করে ইন্টারফেসটি পরিষ্কার এবং দ্রুপাল রাখার সময় খুব শক্তিশালী ক্যোয়ারী তৈরির জন্য বিশাল সুযোগ উন্মুক্ত করে।

আপনার যদি কোনও প্রশ্ন বা সমস্যা থাকে তবে আমাকে জানান।

সম্পাদনা করুন: আমি আসলে এটি করার আরও কিছু পারফর্মেন্ট উপায় পেয়েছি এবং সে অনুযায়ী আমার কোডটি পরিবর্তন করেছি।


বেসট্যাবল প্রয়োজনীয়তাটি "হ্যাক" করার একটি উপায় হ'ল সর্বদা $ ক্যোয়ারী-> সম্পত্তিCondition ('uid', 0, '! =') এর মতো একটি বোগাস সম্পত্তি যুক্ত করা; জিজ্ঞাসা করতে। এটি বেসটিবেলকে সংযুক্ত হতে বাধ্য করে, তবে ইএফকিউ একক ক্ষেত্রের ক্ষেত্রে ভিত্তি টেবিলটি ফেলে যাওয়ার কারণ হিসাবে সামান্য পারফরম্যান্সকে বাধাগ্রস্থ করে তোলে কনডিশন এটি ক্ষেত্রের ডেটা টেবিলটিকে সন্ধান করার উপায়টি দ্রুততর।
টমমি ফোরস্ট্রোম

2
আমি দাবি করি না যে এটি সম্ভবত সবচেয়ে সহজতম উদাহরণ, হিসাবে দাবি করা হয়েছে। আপনি subquery দুটি যোগদানের পক্ষে এবং একটি শর্ত সরাসরি চালু করতে পারবেন না $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

আপনি একবার আপনার ভূমিকার জন্য ব্যবহারকারী আইডিগুলি পেয়ে গেলে আপনি এখনও অ্যান্টিফিল্ডকিউরি () ব্যবহার করতে পারেন, উদাহরণস্বরূপ, কারণ আপনি ফিল্ডকন্ডিশন () বা অন্য কোনও পদ্ধতি ব্যবহার করতে চান।

উপরের উদাহরণে ids 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();

এটিটি আরও ভাল লাগবে যদি এন্টিফিল্ডকিউয়ের একটি যোগদানের পদ্ধতি ছিল।


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_rol_id সংজ্ঞায়িত।
ফ্রাঙ্ক রবার্ট অ্যান্ডারসন

2

এটি গেমটি থেকে একটু দেরীতে হলেও আমার মনে হয় এটি ওপি যা চেয়েছিল। উদাহরণস্বরূপ কোনও স্কিল নয়, সমস্ত দ্রুপাল। আশা করি অন্যরাও এটি কাজে লাগবে। এর সন্ধান আমাকে এখানে নিয়ে যায় এবং আমি এটাই সামনে নিয়ে এসেছি।

    /**
     * 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 এর ভয়ঙ্কর অভিনয় থাকবে।
ডালিন

@ ডালিন, প্রাথমিক যোগ্যতা প্রদত্ত, (অর্থাত্ কোনও এসকিএল, সমস্ত দ্রুপাল) না, আপনি আরও ভাল পারফরম্যান্স পেতে পারে এমন একটি পদ্ধতি হিসাবে কী প্রস্তাব করবেন?
স্বর্ণ 22

1
আরে সোনা! দেখে মনে হচ্ছে db_select () শর্তটি প্রত্যাশা করে $ ভূমিকাটি একটি স্ট্রিং হয়ে গেছে, এবং আপনি যদি একটি পূর্ণসংখ্যার মধ্যে পাস করেন তবে এটি caught ভূমিকা_obj-> মুক্ত হওয়ার উল্লেখের সময় সেট হয়ে যাবে না $ ভূমিকা_obj এ ধরা পড়বে। সম্পাদনা করুন: আমি উত্তরগুলি সম্পাদনা করতে পারি, ওও।
ক্রিস বার্গেস

0

এটি প্রকৃতপক্ষে একটি পুরানো বিষয় এবং আমি প্রচুর ভাল পন্থা পেয়েছি।

আমি @ এলএফ দ্বারা সরবরাহিত সমাধানটিতে কিছুটা উন্নতি করব, কারণ আমি মনে করি যোগদানের সাথে একটি ক্যোয়ারীই সেরা পদ্ধতির। তবে আমি আমার ফাংশনগুলিতে পরামিতি থাকতে এবং ধ্রুবকের উপর নির্ভর না করাও পছন্দ করি। সুতরাং এখানে এটি যায়:

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

আপনি এখানে কীভাবে এন্টিফিল্ডকিউরি ব্যবহার করবেন সে সম্পর্কে একটি ভাল ব্যাখ্যা উদাহরণ পেতে পারেন:

  • http://drupal.org/node/1343708 (এই নিবন্ধে আপনি আরও দরকারী সংস্থান, টিউটোরিয়াল এবং উদাহরণ পাবেন)

তবে ঠিক যেমন বার্দির বলেছিলেন "ইএফকিউ কেবলমাত্র সত্তার সারণির অংশ, একটি সত্তার প্রাথমিক বৈশিষ্ট্যকে সমর্থন করে entity সত্তা সিস্টেমটিতে কোনও ব্যবহারকারীর ভূমিকা কোনওভাবেই প্রকাশিত হয় না।"


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

ব্যবহারকারী মেইলগুলি সংগ্রহ করার জন্য,
সমস্তগুলি

এই উত্তর কি সেই উত্তরের একটি?
মাতোয়েল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.