如何使用EntityFieldQuery

如何使用 EntityFieldQuery

EntityFieldQuery 是 Drupal 7 中新增的一个类,允许利用指定条件获取符合条件的实体。查询条件可以基于属性,字段值以及一些其他的通用的实体元数据。他的语法非常紧凑和实用,而且这一功能由Drupal核心提供,无需另外安装其他模块。

API 手册以及 modules\simpletest\tests\entity_query.test 中的测试用例,可以作为 EntityFieldQuery 的权威文档。”EntityFieldQuery” 类包含于 includes/entity.inc中。本文仅作为一个入门的简介供读者参考。

建立一个查询

下面是一个简单的查询,用来查询所有包含今年教员照片的所有文章。下面的最后五行代码,$result是一个联合数组,第一个键是实体类型,第二个键是实体编号(例如$result['node'][12322] = Node数据 ),注意如果结果集为空,则其中不会有 ‘node’ 键,因此需要用 isset来检查,这里介绍了这种做法的来由。

<?php
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'article')
->propertyCondition('status', 1)
->fieldCondition('field_news_types', 'value', 'spotlight', '=')
->fieldCondition('field_photo', 'fid', 'NULL', '!=')
->fieldCondition('field_faculty_tag', 'tid', $value)
->fieldCondition('field_news_publishdate', 'value', $year . '%', 'like')
->fieldOrderBy('field_photo', 'fid', 'DESC')
->range(0, 10)
->addMetaData('account', user_load(1)); // Run the query as user 1.
$result = $query->execute();
if (isset($result['node'])) {
$news_items_nids = array_keys($result['node']);
$news_items = entity_load('node', $news_items_nids);
}
?>

->entityCondition($name, $value, $operator = NULL)

entityConditions 是绝大多数实体类在 DrupalDefaultEntityController 类都应该支持的查询条件。

entity_type

  • 取值举例:’node’, ‘taxnonomy_term’, ‘comment’, ‘user’, ‘file’
  • 操作符举例:不需要
  • $query->entityCondition(‘entity_type’, ‘node’)

bundle(comment实体类型不支持)

  • 取值举例:’artical’, ‘page’
  • 操作符举例:’=’ 字符串,或者 ‘IN’ 数组
  • $query->entityCondition('bundle', 'article')

revision_id

  • 取值举例:3, 4, 52, 342
  • 操作符举例:整数=, <, >, !=,数组可以使用’IN’和’NOT IN’
  • $query->entityCondition('revision_id', $revision_id, '=')

entity_id 例如 node id

  • 取值举例:3,4,52,342
  • 操作符举例:整数 =, <, >, !=,数组可以使用 ‘IN’ 和 ‘NOT IN’
  • $query->entityCondition('entity_id', array(17, 21,422), 'IN')

->propertyCondition($name, $value, $operator = NULL)

这些条件针对各种实体实现,例如Node, user, comment等。基本上是映射到entity自身的数据表字段中。例如node, users, comment, file_managed, taxonomy_term_data类似的表。用grep/search来查找”Implements hook_entity_info()“能查到实体对应的数据表。

  • status (nodes) 例如: ->propertyCondition('status', 1)
  • type (nodes) 例如: ->propertyCondition('type', array('article', 'page', 'blog'))
  • uid (nodes) 例如: ->propertyCondition('uid', $uid)
  • uri (media) 例如: ->propertyCondition('uri', '%.jpg', 'LIKE')
  • type (media) 例如: ->propertyCondition('type', 'image');

##->fieldCondition($field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $language_group = NULL)

这类条件针对实体的字段来执行。

比如要查找 article node 的 body 字段:->fieldCondition('body', 'value', 'A', 'STARTS_WITH')

  • 字段名称:一般来说,一个表如果叫 field_data_body,实际的字段名就是 body。这个配置保存在 field_config_instance 表中。
  • 列:这是在数据库中对应的列的列名称去掉前缀的部分。body字段的数据库列为 body_value, body_summary, body_format以及 language。真正使用时会使用 value, summary, format 以及 language。 类似的,image 字段会使用 fid, alt 以及 title 作为列名;entity 引用字段会使用target_id以及target_type作为列名。

->propertyOrderBy($column, $direction = 'ASC')

不是对所有属性都生效的。

http://api.drupal.org/api/drupal/includes!entity.inc/function/EntityFieldQuery%3A%3Arange/7

限制查询结果集的范围。

->count()

设置查询只返回数量,例如:

$count = $query->count()->execute();

->addMetaData($key, $object)

在查询中加入其他元数据。因为 EntityFieldQuery 的 fieldCondition 会使用当前用户的权限进行查询,这通常不是我们想要的结果,所以这个方法的一个重要的用途就是用其他用户的身份进行查询,可以在这里使用1号用户进行查询:

$query->addMetaData('account', user_load(1));

随机排序

最简单的随机排序方法就是添加一个 tag,然后进行一次 alter。

<?php
function mymodule_superblock() {
  $query = new EntityFieldQuery();
  $result = $query
    ->entityCondition('entity_type', 'node')
    ->fieldCondition('field_categories', 'tid', array('12','13'), 'IN')
    ->propertyCondition('status', 1)
    ->addTag('random')
    ->range(0,5)
    ->execute();
}
?>

接下来做 alter

<?php
function mymodule_query_random_alter($query){
  $query->orderRandom();
}
?>

参考:hook_query_TAG_alter

排错

根据在 stackexchange 的内容,可以实现 hook_query_alter() 结合 devel的dpm ,对实体字段查询过程进行排错。

<?php
function CUSTOMMODULE_query_alter($query) {
  if ($query->hasTag('efq_debug') && module_exists('devel')) {
    dpm((string) $query);
    dpm($query->arguments());
  }
}
?>

当你往自己的模块中加入了这个函数,就可以利用addTag('efq_debug')来扩展这个查询:

<?php
$q = new EntityFieldQuery;
$q->entityCondition('entity_type', 'node');
  ->addTag('efq_debug');
  ->execute();
?>

相关资源

代码实例

  • modules\simpletest\tests\entity_query.test中的EntityFieldQuery测试。
  • 在核心和其他模块中利用grep/search搜索new EntityFieldQuery()

文章和教程

其他资源

Avatar
崔秀龙

简单,是大师的责任;我们凡夫俗子,能做到清楚就很不容易了。

comments powered by Disqus
下一页
上一页

相关