6.1 实体查询和加载
本课将解释在 Drupal 8 中如何查询实体。
本课内容
- 组装模块 examples/query_example
- 学习实体查询
- 学习实体加载
- 研究、构建
PageExampleController
类
Drupal 历史上核心提供的操作和使用实体系统的方法比较有限,更丰富功能需要捐助模块来提供(Entity API)。Drupal 7 的核心提供了EntityFieldQuery
类,用于以编程的方式搜索实体。这个类包含了几个方法,帮助基于字段值或类属性进行实体查询。更多相关文档请查看 How to use EntityFieldQuery。
Drupal 7 之后,EntityFieldQuery
被核心叫做 entity.query 的服务代替,它可以为特定的实体类型实例化一个查询对象。entity.query
是 QueryInterface
的一个实现。也可以通过 \Drupal 名字空间或依赖注入静态的使用这个服务。
实体查询服务
这个查询服务允许我们取得匹配某种模式的一个节点列表。这类似一个 SQL 查询,但不是写一条语句,而是创建一个查询对象,之后执行它。我们能够调用这个查询对象的函数追加过滤或查询参数。
有两种方式创建查询对象。
基于类的方法(推荐)
之后章节中我们会讨论更多服务(services)内容。本例中,我们将使用类变量和函数获得一个查询对象,使用这个查询对象取得符合模式的节点 ID 列表。
// This function and the next are part of the dependency injection pattern.
// We will explain those in future chapters.
public function __construct(QueryFactory $entity_query) {
$this->entity_query = $entity_query;
}
public static function create(ContainerInterface $container) {
return new static(
// User the $container to get a query factory object.
// This object let's us create query objects.
$container->get('entity.query')
);
}
// This function shows how to
public function myCallback() {
// Use the factory to create a query object for node entities.
$query = $this->entity_query->get('node');
// Add a filter (published).
$query->condition('status', 1);
// Run the query.
$nids = $query->execute();
}
静态方法(不推荐)
大多数代码不会存储在 *.module 文件内了,如果真存储在这里的话是不能使用服务容器的。静态方法同样适用于构建测试。这两种情况你可能需要静态调用 entity.query。
为了静态地使用 entity.query,添加以下内容到你的代码:
$query = \Drupal::entityQuery('node');
如果要使用不同的实体类型,替换 node。在 $query 变量里你可以指定任何其他实体类型的机器名以获得特定实体类型的查询对象。\Drupal 名字空间的 entityQuery() 静态方法是使用 entity.query 服务的一个捷径。
查询实体
下面是一个使用查询对象查询节点实体的例子。
这个基本查询返回站点的发布节点。$nids 变量返回节点 ID 的数组。
/**
* @var $query \Drupal\Core\Entity\Query\QueryInterface
*/
$query = $this->entity_query->get('node')
->condition('status', 1);
$nids = $query->execute();
注意:
象 PHPStorm 这样的 IDE 里,注释有自动完成功能。在我们的例子里,使用了一个变量声明的注解, 说明这个变量是 QueryInterface 类型以及这个类型所在的位置。
查询条件
辅助内容区中的例子除了核实发布状态外还会使用属性和字段条件。这个查询里,我们返回所有被发布的节点 ID,他们的最后更新时间在这个查询运行之前。节点名必须包含“ipsum lorem”。节点的 field_tags 字段等于叫做“test”的分类术语。
在 Drupal 7 里使用 EntityFieldQuery 的时候,propertyCondition
和 fieldCondition 是不同的,但现在 Drupal 8 没有区别。Drupal 8 的 QueryInterface 提供的 condition() 方法合并了属性和字段条件并且允许创建条件组。基于实体引用指定条件也是可以的,这要通过字段名追加 entity.(column) 来指定条件,象上面那个分类术语那样。
$query = $this->entity_query->get('node')
->condition('status', 1)
->condition('changed', REQUEST_TIME, '<')
->condition('title', 'ipsum lorem', 'CONTAINS')
->condition('field_tags.entity.name', 'test');
$nids = $query->execute();
查询条件分组
这个例子演示怎样在复杂查询里创建 AND 或 OR 条件组。我们改变之前的查询,返回满足下面任意一个条件的节点:
- 标题包含“ipsum lorem”
- field_tags 字段引用到“test”分类术语
这个 OR 条件组使用 orConditionGroup 方法创建并作为条件传递给查询对象,你也可以使用 andConditionGroup 创建 AND 条件组。
$query = $this->entity_query->get('node')
->condition('status', 1)
->condition('changed', REQUEST_TIME, '<');
$group = $query->orConditionGroup()
->condition('title', 'ipsum lorem', 'CONTAINS')
->condition('field_tags.entity.name', 'test');
$nids = $query->condition($group)->execute();
查询修订版本
默认,实体查询只返回每个实体最新的修订版本,你可以使用 allRevisions() 获得所有修订版本。
$query->allRevisions();