অ্যান্টিটিফিল্ডকুয়ারির সাথে ওআর ব্যবহার করা


26

আমি আজকের আগে এই করতে হবে ছিল না, কিন্তু মত করুন অথবা প্রশ্নের তা মনে হচ্ছে না EntityFieldQuery, যেহেতু db_orনির্বাচন প্রশ্নের জন্য ব্যবহৃত হয়।

একটি উদাহরণ এমন সমস্ত সত্তার কাছে পাবেন যেগুলির একটি তারিখের ক্ষেত্র রয়েছে যেখানে মানটি শূন্য বা আজকের পরে।

আমি কি কিছু বা কিছু কৌশল অনুভব করছি বা এটি কি সমর্থিত নয়?


আপনি একটি ক্যোয়ারিকেও দুটি ভাগে ভাগ করতে পারেন, এগুলিকে চালান এবং তারপরে ফলাফলগুলিতে যোগ দিতে পারেন।
ভাদিয়াম মাইর্গোরোদ

এর কার্যকারিতা প্রভাবগুলি খুব ভয়ঙ্কর যদি প্রশ্নগুলি বা ডেটার পরিমাণ আরও দূরবর্তী থেকে বেশি হয়।
টমমি ফোর্সট্রাম

1
এটি আমার গুগলের ফলাফলগুলিতে পুরানো তবে উচ্চতর - এটি লক্ষ্য করা উচিত যে আপনি এর জন্য দ্রুপাল ৮
অ্যাগনোকোক্যাটেন

উত্তর:


22

আমি এই সমস্যার সমাধান দেখেছি । ধারণাটি হল addTag()ক্যোয়ারী ব্যবহার করা এবং প্রয়োগ করা hook_query_TAG_alter(), যেখানে আপনার ভাল পুরানো SelectQueryঅবজেক্ট রয়েছে।


আমি এটিকে সঠিক উত্তর হিসাবে নির্বাচন করার প্রস্তাব দেব। ব্লগ পোস্টটি অ্যান্টিটিফিল্ডকিউয়ার্সে বা শর্তযুক্ত হওয়ার জন্য একটি পদ্ধতি সরবরাহ করে। একমাত্র সমস্যাটি হ'ল আপনি সেই পদ্ধতিটির সাথে এসকিউএল নির্ভরতা তৈরি করেন যা EFQs এর পুরো পয়েন্টের বিরুদ্ধে, তবে কমপক্ষে কাজটি সম্পন্ন করে। ভাল লিংক @ মিশেল ধন্যবাদ।
টমমি ফোর্সট্রাম

2
যেহেতু এটি একটি সম্প্রদায়ের উত্তর, এবং এর বেশিরভাগটি একটি বাহ্যিক লিঙ্ক নিয়ে গঠিত তাই আমার মনে হয় কোড বা কমপক্ষে নিবন্ধের কিছু বিষয়বস্তু এই উত্তরটিতে অন্তর্ভুক্ত করা উচিত। কারণ লিঙ্কগুলি মারা যায়। এই বিষয়ে মেটা স্ট্যাকএক্সচেঞ্জ আলোচনা
ডি

মূল নিবন্ধটি বরং দীর্ঘতর এবং ধারণাটি সংক্ষেপে "জিজ্ঞাসায় অ্যাডট্যাগ () ব্যবহার করুন এবং hook_query_TAG_alter () প্রয়োগ করুন"। এরপরে প্রশ্নটি কমেছে "কীভাবে ওআর সিলেক্টকোয়ারী অবজেক্টের সাথে" ব্যবহার করা হবে যা জ্ঞাত বিষয়।
মাইকেল 19

আমি দৃ strongly়ভাবে এই দৃশ্যে একটি নিয়মিত নির্বাচন ক্যোয়ারিতে EFQ রুপান্তরিত করার পরামর্শ দেব। EFQ এর সাথে লেগে থাকা এবং ট্যাগ-ভিত্তিক পরিবর্তনগুলি যা তৈরি করে তা নিয়ে গণ্ডগোলের সাথে তুলনা করে ভয়াবহ।
ফিল্ডস

12

আপনি EntityFieldQueryকিছু পদ্ধতি সাব্লাস এবং ওভাররাইড করতে পারেন ।

শ্রেণীর কোনও অবজেক্টে EntityFieldQuery(যেমন একটি সম্পত্তি শর্ত) যুক্ত হওয়া শর্তগুলি একটি অ্যারেতে যুক্ত হয়।

  public function propertyCondition($column, $value, $operator = NULL) {
    // The '!=' operator is deprecated in favour of the '<>' operator since the
    // latter is ANSI SQL compatible.
    if ($operator == '!=') {
      $operator = '<>';
    }
    $this->propertyConditions[] = array(
      'column' => $column, 
      'value' => $value, 
      'operator' => $operator,
    );
    return $this;
  }

যখন ক্যোয়ারীটি নির্মিত হয়, তখন সেই অ্যারেটি নিম্নলিখিত নীচের মতো লুপে ব্যবহার করা হয় (কোডটি এন্টিফিল্ডকুইয়ারি :: প্রোপার্টি কুইরি () তে উপস্থিত রয়েছে ):

foreach ($this->propertyConditions as $property_condition) {
  $this->addCondition($select_query, "$base_table." . $property_condition['column'], $property_condition);
}

$select_queryএকটি কল থেকে ফিরে মান রয়েছে db_select()


5

আপনি ভয় করতে পারবেন না, ওআরগুলি শ্রেণিকালীনভাবে স্থানীয়ভাবে সমর্থিত নয় EntityFieldQuery

এটির সাথে ক্যোয়ারিতে একটি ট্যাগ যুক্ত করা এক দিক হতে পারে ->addTag(), তারপরে hook_query_TAG_alter()সেই ট্যাগযুক্ত প্রশ্নের জন্য ম্যানুয়ালি ক্যোয়ারীর অভ্যন্তরীণ কাঠামো পরিবর্তন করতে প্রয়োগ করুন ।

এটি করে আপনি বিদ্যমান অবস্থার মধ্য দিয়ে লুপ করতে সক্ষম হবেন এবং আপনার ORযুক্তি যুক্ত করতে প্রয়োজনীয় পরিবর্তন করতে পারবেন । যদিও এটি করার কোনও দুর্দান্ত উপায় নয়; আপনি এখানে একটি উদাহরণ খুঁজে পেতে পারেন ।


5

কোয়েরিগুলিকে 2 তে বিভক্ত করতে হবে না এবং মার্জ করা হবে বা এর মতো কিছু। শুধু ক্যোয়ারী পরিবর্তন করতে হবে

দৃশ্যটি বিবেচনা করুন: আমার কাছে মেশিনের নাম সহ 2 সত্তার প্রকার ছিল: টিনকান স্টেটমেন্ট এবং টিনকান_এজেন্টস

সত্তা উপর 5 সত্তা রেফারেন্স ক্ষেত্র

এর মধ্যে 4 টি নিয়মিত সত্তা রেফারেন্স ক্ষেত্র এবং 5 তম (টিনকান_জেক্ট) একটি বহু-সত্তা-ধরণের রেফারেন্স ক্ষেত্র, প্রতিটি রেফারেন্স ক্ষেত্র 'এজেন্ট' টাইপের একটি সত্তাকে উল্লেখ করে।

টিনকান_জেক্টের রেফারেন্স ক্ষেত্র এজেন্ট এবং ক্রিয়াকলাপগুলি (একটি তৃতীয় সত্তার প্রকার) উল্লেখ করতে পারে। কোনও এজেন্টের একটি সম্পত্তি অবজেক্ট টাইপ থাকে যা এজেন্ট বা গ্রুপ হতে পারে।

আমি যে কোনও বিবৃতি খুঁজে পেতে চাই যা উল্লেখযোগ্য ক্ষেত্রগুলির যে কোনও একটিতে বেশ কয়েকটি সম্ভাব্য এজেন্টের একটিকে রেফারেন্স করে। ক্ষেত্রের শর্তগুলির মধ্যে আমাদের একটি ওআর অপারেটর প্রয়োজন, তবে আমাদের বহু-সত্তার প্রকারের রেফারেন্স ক্ষেত্রের অবজেক্ট_ টাইপও পরীক্ষা করে দেখতে হবে এবং এটি দুটি সম্ভাবনার মধ্যে একটি হতে পারে তা নিশ্চিত করে নেওয়া উচিত।

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

    $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'tincan_statement');

    $all_agents = array(4,10); //entity_ids to search for
    $query->addTag('tincan_statement_get_agents');
    $query->fieldCondition('tincan_actor', 'target_id', $all_agents, 'IN'); 
    //need OR between fields conditions
    $query->fieldCondition('tincan_authority', 'target_id', $all_agents, 'IN');
//need OR between fields conditions
    $query->fieldCondition('tincan_instructor', 'target_id', $all_agents, 'IN');
//need OR between fields conditions
    $query->fieldCondition('tincan_team', 'target_id', $all_agents, 'IN');
//need OR between fields conditions
//but then nested in the OR structure we need an AND for two columns of the multientity type reference field tincan_object
    $query->fieldCondition('tincan_object', 'target_id', $all_agents, 'IN');
    $query->fieldCondition('tincan_object', 'object_type', array('Agent', 'Group'), 'IN');
    $results = $query->$execute();

সমাধান: উপরের এন্টিফিল্ডকিউরিতে বিজ্ঞপ্তি

 $query->addTag('tincan_statement_get_agents');

এই কোয়েরিকে ট্যাগ করে, হুক_উইকি_এটিএজি_এলটার () প্রয়োগের অনুমতি দেয়

/**
 * Implements hook_query_TAG_alter()
 * alters the query for finding agents with or without the related_agents flag
 * used for Statement API Get processor EntityFieldQuery
 */
function tincan_lrs_query_tincan_statement_get_agents_alter(QueryAlterableInterface $query) {
  //need to or the search for all the fields (actor, object, authority, instructor, team)
  // the object_type of the object field needs to be Agent OR Group

  $conditions =& $query->conditions();
  // dsm($conditions);  //dsm() is your friend! comes with devel module
  $agent_grouping_condition = db_or(); 
  $object_parameters = array();
  $x = 0;
  foreach ($conditions as $key => $condition) {
    if (is_numeric($key) && isset($condition['field']) && is_scalar($condition['field'])) {
      if ( (strpos($condition['field'], 'tincan_object_object_type') !== FALSE  ||
          strpos($condition['field'], 'tincan_object_target_id') !== FALSE ) && $condition['operator'] == 'IN') {
  //u
            unset($conditions[$key]);
            $object_parameters[$x]['field'] = $condition['field'];
            $object_parameters[$x]['value'] = $condition['value'];
            $object_parameters[$x]['operator'] = $condition['operator'];
            $x += 1;
          }

       if(strpos($condition['field'], 'tincan_actor_target_id') !== FALSE ||
          strpos($condition['field'], 'tincan_instructor_target_id') !== FALSE ||
          strpos($condition['field'], 'tincan_team_target_id') !== FALSE ||
          strpos($condition['field'], 'tincan_authority_target_id') !== FALSE ) {
            unset($conditions[$key]);
            $agent_grouping_condition->condition($condition['field'], $condition['value'], $condition['operator']);

      } 
    }
  }

  // create new AND condition to nest in our OR condition set for the object parameters
  $object_condition = db_and();
  foreach($object_parameters as $key => $param) {
    $object_condition->condition($param['field'], $param['value'], $param['operator']);
  }

  $agent_grouping_condition->condition($object_condition);

  $query->condition($agent_grouping_condition);

  //By default EntityFieldQuery uses inner joins, change to left
  $tables =& $query->getTables();

  foreach($tables as $key => $table) {
    if (strpos($key, 'field_data_tincan_object') !== FALSE ||
        strpos($key, 'field_data_tincan_actor') !== FALSE ||
        strpos($key, 'field_data_tincan_authority') !== FALSE ||
        strpos($key, 'field_data_tincan_instructor') !== FALSE ||
        strpos($key, 'field_data_tincan_team') !== FALSE ) {
          if(!is_null($table['join type'])) {
            $tables[$key]['join type'] = 'LEFT';
          }
    }
  }

}

2

ওপি x তারিখের সাথে শূন্য বা x এর চেয়ে বড় সংস্থার সন্ধান করতে চায়, আমি নোডগুলির জন্য কোনও ভাষা সংজ্ঞায়িত বা ব্যবহারকারীর ভাষা জিজ্ঞাসা করতে চেয়েছিলাম। addTag()একটি আসল বা বিবৃতি যুক্ত করার জন্য সেরা সমাধান, তবে আমার ক্ষেত্রে এটি ওভারকিল হবে। আমার খুব সাধারণ বা ভাষা ব্যবহার করে একটি অ্যারে ব্যবহার করে ভাষা সম্পত্তির সন্ধান করা সম্ভব:

$query->propertyCondition('language', array($GLOBALS['language']->language, LANGUAGE_NONE), 'IN');
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.