跳转到主要内容
sina_门前小雨 提交于 14 April 2016
 

插件和实体(Plugins and Entities)

我们在前面的章节中学习了Drupal 8的结构和它是如何处理网络请求的。但我们没怎么学习Drupal时如何被构建的。在我们学习具体的核心模块代码之前,有一些Drupal 8重要的新概念需要理解。这一章里我将讲述它们。

配置(Configuration)

Drupal 8中配置系统有了令人欣喜的改变。最显著的变化是配置现在存储在'/sites/{name}/files/config_{HASH}/active'目录下的许多YAML文件中。这些文件的名字定义了文件中存储了关于哪些配置。举个栗子,'node.settings.yml'文件中存储了node模块的配置,'views.view.content.yml'文件中存储了机器名为content的视图的定义。Drupal使用配置前缀(config prefixes完成了这些。这名意思应该是这样命名文件的方式就是config prefixes。

 

你可能认为配置文件是非常死板的(inflexible)。但是在实践中我们甚至可以用YAML语法创建关联数组(associative array)。更近一步,Drupal提供了一个Config对象,它可以用来运行中改变配置文件,这样我们就不用手动修改了。当你使用Drupal管理界面创建新的字段、节点、区块或视图的时候,配置文件也被自动创建了。节点的内容和数据仍然存储在数据库中,如果不这样的话你怎么查询啊(看上去没框架打算把数据存储直接集成进去)。

模块根目录下也许会有conf子目录。当模块启用时,这个目录中的所有文件都会被复制到站点的配置目录中。当文件被复制或是清空缓存时,站点的配置目录中的配置文件会被自动发现并且直接应用。使用这种方式,模块可以添加新的节点、图像样式、视图等等,而不用像在Drupal 7中那样靠hook_node_info钩子实现。

配置文件可以很容易地被复制到其它的位置,这有利于批量更改配置。原文意思是像更改舞台布景似地更改配置。

配置文件应该会有一个模板,它会详细地描述视图、区块、图像样式等等应该怎样定义。这样配置文件就能被更好的被验证和翻译。

实体

Drupal 7引入了实体的概念。它们是被生成的具有相同功能的对象。举个例子,我们可以在视图中引用的字段被附加了自动生成的存取方法。实体概念的功能非常强大。在Drupal 8中,实体的概念变得更为重要更加靠近CMS的中枢。不单单是节点、分类词语(taxonomy terms)(分类用的标签)、用户这些内容数据,还有视图、行动、图像样式等等这些非字段数据,都是由Entity类扩展而来。而且捆绑筐(bundles)像是节点类型、词汇表(vocabularies)现在也都是实体了。这样做的原因是,尽管这些对象类型没有字段,但作为实体它的生成方式更方便,例如可由配置文件里存储的内容生成或是基于实体名的日程参数通过自动转换生成。

 

实体的属性使用由特性(attributes)定义。举个栗子,特性能够指定实体是不是有字段,或是服务于其它实体的捆绑筐。实体也许存储在依赖控制器的配制文件中,或者用其它方法存储。如果控制器是ConfigStorageController类或是由它扩展而来,实体以配置文件的方式存储。虽然用配置文件存储也不错,但这意味着你不能对它们使用数据库查询。如果你想在它们中查询什么,你要把它们都加载了,然后使用PHP循环语句遍历每个实例。如果数据库存储更为优先(preferred),像是节点和用户,将会使用FieldableDatabaseStorageController类存储。这样的实体有节点、用户以及分类词语等等。最终内容是不能通过配置文件迁移的。我也不是很清楚有没有可能有一个能存储字段配置文件的控制器。(有的话迁移就方便多了)

为了更好的理解实体属性,我建议你去查看ImageStyle类的注释。这是一个纯粹用配置文件实现的实体。相对的,分类词语是有字段的使用数据库存储的实体,还有是分类筐的词汇表实体。

插件

插件可以看作是使用面向对象模式实现的钩子。模块插件里包含了用户自定义区块、图像效果等等。

最明显的例子是BlockBase虚类,如果想要添加区块就必须派生它,就像论坛模块的ActiveTopicsBlock类一样。像是访问权限检查、创建视图、提交表单区块之类的方法必须被覆盖重写。

插件类型使用插件管理器(plugin manager)(看起来像是个服务)定义。命名空间的列表和子目录结构用来描述插件应该在哪。通过这种方式,任何模块都可以添加插件。一个被注释为插件的类会被认为是插件。依据插件类型的不同,注释中必须具有某些配置。

 

Drupal静态类

Drupal 8的大部份核心代码是面向对象的,只有模块钩子的部分还是面向过程的。这是个问题,因为Symfony是完全面向对象的框架。在Symfony中如果你想创建一个依赖于某个服务的方法,你必须创建一个新的服务并且在服务容器中定义依赖关系。如果你需要用Drupal的钩子实现一个独特的服务,你不能使用Symfony中的机制,因为从一开始它就不是一个类(更别说面向对象了)。Druapl静态类就是为了应对这种情况。它可以在面向过程的上下文中获取服务,通过Drupal::service('{service id}')或是特殊的服务存取器Drupal::request()、Drupal::currentUser()、或Drupal::entityManager()等等。更进一步,Druapl静态类还提供了一些方便的辅助函数,像是Drupal::url(),这个函数等价于Drupal 7中的url()函数。

node.module中的node_access方法使用Drupal静态类的例子:

function node_access($op, $node, $account = NULL, $langcode = NULL) {

  $access_controller = \Drupal::entityManager()->getAccessController('node');

  ...

  return $access_controller->access($node, $op, $langcode, $account);

}

 

总结(Conclusion)

这篇文章中我们学习了Drupal 8是怎样被搭建起来的,和它与Symfony 2框架结构的对比。我们了解了服务容器管理所有的服务和它的配置方式。之后我们又学习的Drupal核心是怎样进行日程分发(routing)和处理网络请求的。最后我们介绍了Drupal 8中的一些重要的新概念,Drupal类、插件和配置。

我希望这些信息能够帮助你探索和学习Drupal 8。我你能够掌握模块开发并为整个项目贡献模块。

祝你好运!

Drupal 版本