Sorguları ikiye bölmeye ve birleştirmeye ya da onun gibi bir şeye gerek yok. Sadece sorguyu değiştirmelisin
Senaryoyu inceleyin: Makine isimlerinde 2 varlık tipim vardı: tincan deyimleri ve tincan_agents
Varlık üzerinde 5 varlık referans alanı
Bunlardan 4 tanesi normal varlık başvuru alanıdır ve 5'inci (tincan_object) çok varlıklı bir başvuru alanıdır, her başvuru alanı 'Ajan' tipi bir varlığa atıfta bulunur.
Tincan_object başvuru alanı, Acentelere ve Faaliyetlere başvurabilir (üçüncü bir varlık türü). Bir Ajanın, Ajan veya Grup olabilen bir özelliği object_type vardır.
Herhangi bir referans alanında, olası birkaç Ajandan birine referansta bulunan herhangi bir Bildirimi bulmak istiyorum. FieldConditions arasında bir OR işlecine ihtiyacımız var, ancak çok varlıklı tür başvuru alanının object_type değerini de kontrol etmemiz ve bunun iki olasılıktan biri olduğundan emin olmamız gerekiyor.
Aşağıdaki kod mümkün olan en basit ifadeyi temsil eder, çözümümüzde sorgunun birçok başka koşulu, alanı vb. Vardı, bu yüzden şartların sırasına göre sayılmaması gereken kod ya da bu alanların tümü sorgulanıyor olsa bile.
$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();
Çözüm:
Yukarıdaki EntityFieldQuery'deki uyarı
$query->addTag('tincan_statement_get_agents');
Bu, sorguyu etiketleyerek hook_query_TAG_alter () işlevinin uygulanmasına izin verir
/**
* 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';
}
}
}
}