“中国要复兴、富强,必须在开源软件领域起到主导作用,为了国家安全和人类发展,责无旁贷,我们须为此而奋斗”——By:云客
基本Base字段和bundle字段:
一个可字段化的实体类型自身定义的字段称为基本字段(非bundle定义,模块可以通过钩子entity_base_field_info添加定义),她们存在于所有的bundle中,也就是说所有bundle可用,基本字段定义可以通过模块的hook_entity_base_field_info_alter()钩子修改,这种修改作用于全部bundle,如果要作用于某个bundle可以使用'base_field_override'配置实体覆写,而由bundle定义的字段称为bundle字段,它们可能不存在于其他bundle中,在可字段化实体接口中bundleFieldDefinitions方法返回的字段包括被覆写的基本字段定义。
字段定义和字段储存定义:
在字段定义中将和储存有关的定义独立出来,所以字段定义有两个层面,有两个接口:
字段定义(也可以称为full定义,或完整定义,因为它可以返回储存定义)的接口为:
Drupal\Core\Field\FieldDefinitionInterface
字段储存定义的接口为:
Drupal\Core\Field\FieldStorageDefinitionInterface
储存定义表明字段应该如何储存,因此它并不关心bundle,所有bundle都共享通用的储存定义,然而不同的bundle可能提供一些不一样的字段信息,比如约束设置、label、 description等等,所以用字段定义来处理具体的字段,完整定义是需要bundle的。以上两个接口中字段定义更具体,字段储存定义更通用。
对应的系统中提供了两个配置实体来储存他们:
字段配置实体和字段储存配置实体
他们由字段模块提供。
在后台管理内容类型时字段需要先定义再使用,那么系统内部是如何进行定义呢?
字段配置基类:
类:Drupal\Core\Field\FieldConfigBase
这是一个抽象基类,用于供字段配置对象使用(在系统中字段配置实体和基本字段覆写配置实体便继承自她),比如我们在管理后台新建内容类型添加字段时就用了到她,她实现了字段配置接口:
Drupal\Core\Field\FieldConfigInterface
(该接口继承自Drupal\Core\Field\FieldDefinitionInterface)
字段配置接口用于支持字段的配置设置,该基类同时继承了配置实体基类,这样为其提供了配置储存等多种功能
字段配置实体field_config:
实体类型id:field_config
类:Drupal\field\Entity\FieldConfig
继承自:Drupal\Core\Field\FieldConfigBase;
注意它实现了两个字段配置接口:
Drupal\Core\Field\FieldConfigInterface
Drupal\field\FieldConfigInterface
这两个字段配置接口都继承自同样的接口(字段定义接口和配置实体接口),一个由核心定义,一个由字段模块定义,只有细微差别
字段配置实体使用如下储存处理器:
Drupal\field\FieldConfigStorage
最终使用了配置实体的储存处理器:
Drupal\Core\Config\Entity\ConfigEntityStorage
见本系列配置实体储存处理器主题
要配置并识别一个字段,需要在系统中为该字段分配一个唯一标识id,格式由三部分组成:实体类型id、bundleID、字段名,以点号连接,如下:
node.article.body
user.user.field_main_image
node.wanbiao.title
字段配置实体储存和操作该id所代表的字段的相关信息,在数据库配置表中是以如下格式储存配置信息的:
模块名.配置前缀.字段id
如:field.field.node.article.field_image
字段储存配置实体field_storage_config:
实体类型id:field_storage_config
类:Drupal\field\Entity\FieldStorageConfig
继承自:Drupal\Core\Config\Entity\ConfigEntityBase
实现接口:Drupal\field\FieldStorageConfigInterface
该接口继承了以下接口:
配置实体接口:Drupal\Core\Config\Entity\ConfigEntityInterface;
字段储存定义接口:Drupal\Core\Field\FieldStorageDefinitionInterface
该实体对应于字段储存定义,因此它不关心bundle,字段id为:
(实体类型id.字段名)
如:node.body
字段储存配置信息被储存在数据库配置表中,储存id为:
模块名(field).配置前缀(storage).字段id
如:field.storage.node.body
该实体的储存处理器为:
Drupal\field\FieldStorageConfigStorage
直接继承配置实体储存:Drupal\Core\Config\Entity\ConfigEntityStorage
见本系列配置实体储存处理器主题
当我们在建立bundle时,可能会对基本字段进行改动,比如建立内容类型时就可能对节点字段进行改动,最常见的就是对标题字段进行覆写,那么就需要字段覆写了,系统使用基本字段覆写配置实体来储存被覆写的基本字段定义:
基本字段覆写配置实体:
实体id:base_field_override
实体类:Drupal\Core\Field\Entity\BaseFieldOverride
她和前文的字段配置实体一样继承自字段配置基类,该基类实现了字段配置接口:
Drupal\Core\Field\FieldConfigInterface
该接口又继承了字段定义接口和配置实体接口:
Drupal\Core\Field\FieldDefinitionInterface
Drupal\Core\Config\Entity\ConfigEntityInterface
她既是字段定义对象也是一个配置实体,储存着被bundle覆写的基本字段定义,和字段配置实体一样,被覆写字段的id由三部分组成(实体类型id、bundleID、字段名,以点号连接),配置前缀为:base_field_override,提供模块为核心core,所以在数据库配置表中的配置名为:
core.base_field_override.字段id
如:core.base_field_override.node.article.path
这个实体比较简单,可以看出配置项中许多都可以进行覆写,其中由代理模式设计的方法得到的配置项不能覆写,如:isDisplayConfigurable($context)、isReadOnly()等等
伪字段:
“extra fields”或者“pseudo-field”,这在本系列的实体字段管理器(容器服务id:entity_field.manager)中讲述。
字段事件:
请参阅drupal的事件派发机制,可以查看本系列的“核心处理流程HttpKernel”主题理解事情派发器。键值储存可参阅本系列的“状态信息state及键值储存系统”主题
服务id:“field_definition.listener”
Class:Drupal\Core\Field\FieldDefinitionListener
该服务响应字段定义的创建、更新、删除操作,代理了实体储存处理器的相应方法,并维护键值储存系统和实体字段管理器中的字段映射数据
服务id:“field_storage_definition.listener”
Class:Drupal\Core\Field\FieldStorageDefinitionListener
该服务响应字段储存定义的创建、更新、删除操作
字段卸载验证:
这将在模块安装与卸载主题中讲解
字段组件重点总结:
一个字段field对象是由相同类型的条目items对象构成的列表数据对象,条目items对象是一个复合数据对象(复合数据对象用法类似php的关联数组,但不同之处是定义前必须先知道数据定义,有哪些键,每个键是什么数据,而php的关联数组不必预先知道),每种类型的条目items代表着一种字段类型,系统在数据库中根据字段类型建立对应的一张数据表,叫做字段表,每个条目items对象对应数据库表中的一行记录,条目items对象可以有一个或多个属性,也就是每种字段类型可以有一个或多个属性,如email 字段只有 'value'属性 ,link 字段有 'title' 、 'url' 属性, text字段有 'value', 'summary', 和'format'属性,每个属性对应字段表中的一个列(这些列在字段条目接口的schema方法或字段储存定义的getSchema()方法中依据SchemaAPI指定),但反之则不然,字段表需要其他许多列来储存必要的数据,如版本号、语言代码、实体id、bundle等等。
反馈互动