Không cần phải chia các truy vấn thành 2 và hợp nhất hoặc bất cứ điều gì như thế. Chỉ cần thay đổi truy vấn
Hãy xem xét kịch bản: Tôi có 2 loại thực thể với tên máy: câu lệnh tincan và tincan_agents
5 trường tham chiếu thực thể trên thực thể
4 trong số đó là các trường tham chiếu thực thể thông thường và thứ 5 (tincan_object) là trường tham chiếu nhiều loại thực thể, mỗi trường tham chiếu tham chiếu một thực thể loại 'Tác nhân'.
Trường tham chiếu tincan_object có thể tham chiếu Đại lý và Hoạt động (loại thực thể thứ ba). Một Tác nhân có thuộc tính object_type, có thể là Đại lý hoặc Nhóm.
Tôi muốn tìm bất kỳ Tuyên bố nào tham chiếu một trong một số Đại lý có thể, trong bất kỳ trường tham chiếu nào. Chúng ta cần một toán tử OR giữa các trườngConditions, nhưng chúng ta cũng cần kiểm tra object_type của trường tham chiếu loại đa thực thể và đảm bảo rằng đó là một trong hai khả năng.
Mã dưới đây đại diện cho đơn giản nhất có thể, trong giải pháp của chúng tôi, truy vấn có nhiều điều kiện, trường khác, v.v ... vì vậy mã cần thiết để không tính theo thứ tự các điều kiện hoặc ngay cả khi tất cả các trường này được truy vấn.
$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();
Giải pháp:
Lưu ý trong EntityFieldQuery ở trên
$query->addTag('tincan_statement_get_agents');
Điều này gắn thẻ truy vấn, cho phép thực hiện hook_queryiah_alter ()
/**
* 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';
}
}
}
}