使用或与EntityFieldQuery -- entities 领域 和 database 领域 drupal 相关 的问题

Using OR with EntityFieldQuery


27
vote

问题

中文

我从来没有在今天之前做过这一点,但它看起来不像你可以用 EntityFieldQuery 询问,因为 db_or 用于选择查询。

一个例子将到达所有具有日期字段的实体,其中值为null或今天之后。

我缺少某些东西或一些技巧,或者这是不支持的吗?

英文原文

I have never had the need to do this before today, but it doesn't seem like you can make OR queries with EntityFieldQuery, since db_or is used for select queries.

An example would get to all entities that has a date field where the value is null or after today.

Am I missing something or some trick or is this simply not supported?

     
     
     

回答列表

22
 
vote
vote
最佳答案
 

我已经看过一个解决这个问题的解决方案。这个想法是在查询中使用 addTag() ,实现 hook_query_TAG_alter() ,您可以在那里有很好的旧<代码> SelectQuery 对象。

 

I have seen a solution of this problem. The idea is to use addTag() in query and implement hook_query_TAG_alter(), where you have good old SelectQuery object.

 
 
       
       
12
 
vote

您可以Sublass EntityFieldQuery 并覆盖某些方法。

添加到类 99887665 (例如属性条件)的对象中的条件被添加到数组中。

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

在构建查询时,然后在类似于以下一个的循环中使用该数组(代码在 entityfieldquery :: propertyquery()):

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

$select_query 包含从呼叫返回的值 db_select()

 

You can sublass EntityFieldQuery and override some methods.

The conditions that are added to an object of class EntityFieldQuery (e.g. a property condition) are added to an array.

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

When the query is built, that array is then used in a loop similar to the following one (the code is present in EntityFieldQuery::propertyQuery()):

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

$select_query contains the value returned from a call to db_select().

 
 
5
 
vote

你不能恐怕, EntityFieldQuery class没有本然没有得到本地支持。

一个方式,它可能是用 ->addTag() 为查询添加标记,然后实现 hook_query_TAG_alter() 要手动更改查询的内部结构,查询包含该标签的查询。

执行此操作,您将能够循环通过现有条件,并进行必要的更改以添加 OR 逻辑。然而,这不是一个很重要的方法;您可以找到一个在这里。

 

You can't I'm afraid, ORs are not natively supported by the EntityFieldQuery class.

One way round it might be to add a tag to the query with with ->addTag(), then implement hook_query_TAG_alter() to change the internal structure of the query manually for queries containing that tag.

Doing this you will be able to loop through the existing conditions and make the necessary alterations to add your OR logic. It's not a pretty way to do it though; you can find an example here.

 
 
5
 
vote

无需将查询拆分为2并合并或类似物。只需要改变查询

考虑方案: 我有2种带有机器名称的实体类型:Tincan语句和Tincan_agents

5实体上的实体参考字段

其中4个是常规实体参考字段,第5个(Tincan_Object)是一个多实体类型参考字段,每个参考字段引用类型'代理'的实体。

Tincan_Object参考字段可以引用代理和活动(第三实体类型)。代理具有属性object_type,可以是代理或组。

我想在任何参考字段中找到引用多个可能代理中的一个的任何语句。我们在FieldConditions之间需要一个或运算符,但我们还需要检查多实体类型参考字段的object_type,并确保它是两种可能性之一。

下面的代码代表最简单的可能,在我们的解决方案中,查询有许多其他条件,字段等......所以即使正在查询条件的条件顺序所需的代码也是如此。

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

解决方案: 在上面的EntityFieldQuery中通知

   $query->addTag('tincan_statement_get_agents');   

此标记查询,允许实现hook_query_tag_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';           }     }   }  }   
 

No need to split queries into 2 and merge or anything like that. Just need to alter the query

Consider the scenario: I had 2 entity types with machine names: tincan statements, and tincan_agents

5 entity reference fields on the entity

4 of them are regular entity reference fields and the 5th (tincan_object) is a multi-entity-type reference field, each reference field references a entities of type 'Agent'.

The tincan_object reference field can reference Agents and Activities (a third entity type). An Agent has a property object_type, which can either be Agent or Group.

I want to find any Statement that references one of several possible Agents, in any of the reference fields. We need an OR operator between the fieldConditions, but we also need to check the object_type of the multi-entity type reference field, and make sure it is one of two possibilities.

The code below represents the simplest possible , in our solution the query had many other conditions, fields, etc... so the code needed to not count on the order of conditions, or even if all of these fields were being queried.

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

Solution: Notice in the above EntityFieldQuery

 $query->addTag('tincan_statement_get_agents'); 

This tags the query, allowing implementation of hook_query_TAG_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';           }     }   }  } 
 
 
2
 
vote

op想要查询具有日期null或大于x的实体,我想查询没有定义语言或用户语言的节点。 addTag() 是添加实际或陈述的最佳解决方案,但在我的情况下会矫枉过正。我非常简单或可以通过查找数组中的语言属性使用:

  $query->propertyCondition('language', array($GLOBALS['language']->language, LANGUAGE_NONE), 'IN');   
 

The OP wants to query for entities with date null OR bigger than x, I wanted to query for nodes with no language defined OR the user's language. addTag() is the best solution for adding an actual OR statement, but would be overkill in my case. My very simple OR can be accomplished by looking up the language property in an array using:

$query->propertyCondition('language', array($GLOBALS['language']->language, LANGUAGE_NONE), 'IN'); 
 
 

相关问题

6  将标题添加到允许多个图像的图像字段  ( Add a caption to an image field that allows multiple images ) 
好的,标题不是有史以来英语最好的例子,但我希望你能得到我的意思... 我已经逆住drupal中的错误,其中它不会检查图像字段中标题值的长度(http://drupal.org/node/916446),我正在使用该字段来存储图像中显示在图像下的div中的标题。 是否有一种方法可以允许标题字段保存更多信息,甚至更好(...

1  CCK文本字段未显示在视图字段中或过滤器中  ( Cck text field does not appear in views fields nor filters ) 
我在我的toc中有一个cck文本字段。但是,它不会显示在视图字段下的选择,也不显示视图过滤器。 我尝试了清除缓存并刷新模块列表,没有运气。 任何可能发生的内容? ...

3  内容类型中的D7相关节点  ( D7 related nodes within a content type ) 
请原谅我,如果这是一个总是的noob问题,而是无论如何。 我有一个内容类型'人'。我要添加到"人" 的一个字段是一个亲戚字段,我希望它是自动完成或下拉列表。我很确定我可以想到这一点。问题是,如何使用已创建的所有"人称内容的名称" 下拉列表(或自动完成)填充下拉列表(或AutoComplete)? 也,我正在使用我标题...

1  根据Drupal 7中的用户角色限制字段列表条目  ( Restricting field list entries based on user role in drupal 7 ) 
我正在使用drupal 7中的字段权限模块来限制对基于用户角色创建的列表字段的访问权限,这很好。但是有没有办法根据用户角色限制该列表的内容? 例如: 对于用户角色1,我希望自定义字段列表显示: 苹果 香蕉 葡萄 橙色 对于用户角色2,我希望自定义字段列表显示: 苹果 葡萄 ...

0  如何将分类系统添加到Page - node.tpl.php?  ( How do you add taxonomy with fields to page node tpl php ) 
我正在尝试添加到我的节点页面一个分类列表,其中包括我添加到分类学的字段。我能够使用以下代码将字段从相应的注释从相应的注释添加到我的页面 - node.tpl.php文件: <?php $field_country = field_view_field('node', $node, 'field_country'...

3  是否会在内容类型中删除字段删除数据?  ( Does deleting a field in a content type remove the data ) 
a 先前发布的问题似乎假设如果在他/她的论坛内容类型中删除该字段,则在数据库中删除数据。我认为,如果您添加违法,则该字段仍然存在,数据仍然可用。我不愿意在我当前的网站上测试这一点,以防我错了:}。 ...

1  扩展用户配置文件的最佳选择  ( Best option to extend user profile ) 
如果我想在用户配置文件页面中添加一个新选项卡,我们应该在此选项卡中创建新节点类型并在此选项卡中创建新节点类型并呈现,或者在此选项卡中介绍一个描述Résumé的表格每个用户,在此选项卡中开发添加/编辑/删除表单并呈现它们? 现在,我实现了第二个选项,我想知道通过将我的SQL表映射到实体来与字段API更容易,以便我不需要...

1  如何使用代码计算和永久存储字段值  ( How do i calculate and permanently store a field value with code ) 
我想知道如何手动在CCK节点内手动插入一些PHP代码。 我所拥有的是drupal 6的以下代码: $output .= '<br>'; $mor = _pitch_detalle($cid, $previamente, $luego); if (sizeof($mor) > 0) { $output .= t...

1  使用描述迁移文件  ( Migrating files with descriptions ) 
我当前将pdf文件迁移到内容类型中。我想知道如何使用更有意义的链接填充文件信息描述字段(例如,给出每个导入的文件的描述)。 $arguments = MigrateFileFieldHandler::arguments(drupal_get_path('module', 'my_migrate').'/docs'...

1  单独输出节点字段  ( Outputting node fields individually ) 
我有一个节点模板,但不是输出$内容,我希望通过单独打印每个字段来更好地控制模板显示。 下面是我想要包含的字段: $title field_img $body 我会用哪些代码替换?此外,使用该方法有任何显着的缺点吗? ...

0  将CCK字段添加到SimpleNews电子邮件时事通讯  ( Adding cck fields to simplenews email newsletter ) 
我正在使用,但是我需要添加几个附加cck通讯中包含的每个节点的字段。看作为模板文件电子邮件通讯使用(SimpleNews-Newsletter-Body.tpl.php)只是使用$ body变量来输出内容,我将在哪里指示简化为我发送的每个节点添加我的额外cck字段? ...

3  图像字段浏览器选项  ( Image field browser option ) 
是否有任何方法可以改变默认的Drupal 7映像字段以允许浏览服务器选项以及默认上载文件选项?类似的像 imce 或 ckfinder 但是对于图像字段而不是内容(文本)字段。 似乎这可能非常有用,我真的没有看到任何提供这种功能的模块。 ...

0  我们如何在CCK字段中输出未过滤的HTML  ( How can we output unfiltered html in a cck field ) 
这似乎是最简单的事情,但由于某种原因,我们无法实现这一点。 我们为我们的"产品" 内容类型创建了4个额外的CCK字段。 我们在这些字段中输入简单的HTML,并希望显示这些字段,如未过滤在节点输出上。 无论我们做什么,它总是作为纯文本输出,剥离所有HTML。 Weve看到了众多引用字段设置中的"文本处理" 选项,但它们...

5  内容类型的键值字段  ( Key value field for content types ) 
我有一个内容类型,包括许多(任意数字)键/值对组成。 我正在寻找的是一个像选项元素,我可以添加到我的自定义中内容类型。是否有这样的模块? ...

1  提供CCK字段不可编辑的值?  ( Give a cck field a non editable value ) 
是可能的,不仅要为CCK字段提供默认值,还使其不可编辑的用户? ...

1  从饲料节点馈送项目字段  ( Feed items field from feed node ) 
我正在寻找一种方法,使饲料项目从导入期间从其父Feed Importer节点继承字段值。此想法是稍后在视图过滤中使用此字段值。在我的情况下,此字段包含引用节点的NID值,对于Feed Importer节点以及其所有馈送项目以及其他导入者及其饲料项目的馈送项目应该相同。 我找到了一个安静的类似问题: http://...

1  渲染一个CCK字段,只有Drupal 6中的节点对象  ( Render a cck field with only the node object in drupal 6 ) 
如果我有一个节点对象,并且想渲染给定的cck字段,我该怎么办?我不是在节点模板页面上或在nodeapi挂钩上的意思,一般。 我的自定义cck字段的 theme_mymodule_formatter_default 函数需要$元素数组 - 在节点页面上调用此函数时,$元素是一个带键的数组,包括以下内容: #form...

1  设置日期字段以要求结束日期  ( Setting up a date field to require an end date ) 
我试图通过hook_install创建模块的自定义内容类型。当我创建日期类型(从日期模块)时,我希望它需要结束日期(通过GUI设置字段时有一个复选框)。这是字段的设置数组: field_application_discipline_id (Array, 13 elements) #type (String, 2...

1  模块dev:如何将按钮附加到字段?  ( Module dev how to attach a button to a field ) 
我想构建一个模块,其中用户可以启用每个字段的按钮,并且当用户点击它时,它会获得现场内容并将其发布到服务。 如果有这样的模块,那将是伟大的,以及一个例子。 ...

2  Drupal 7中具有多个值的字段的自定义安排  ( Custom arrangement for fields with multiple values in drupal 7 ) 
在Drupal 6中,我用于为具有多个值的CCK字段制作各种自定义标记。通常情况下发生这种情况,当我想在表格中铺设画廊时:我曾经进入相关的tpl.php文件,则抓住相关的$ field_fieldname变量,循环贯穿它,并打印出它的"查看" 键其中包含风格的缩略图,通常与原始图像和任何东西相关联。 现在,我有点困惑...




© 2021 it.wenda123.org All Rights Reserved. 问答之家 版权所有


Licensed under cc by-sa 3.0 with attribution required.