logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

9.11. Drupal 实体(Entity)API。创建自定义实体类型。使用 Drupal Console 生成实体类型。

16/10/2025, by Ivan

我们已经了解了 Form API、Fields API,并且知道 Drupal 中的数据是如何存入数据库的。现在让我们来看看所有 Drupal 网站的基础——Entity API(实体 API)。

你可能已经注意到,字段(fields)并不是独立存在的,而是“附加”在实体(entity)上的:节点(nodes)、区块(blocks)、分类术语(taxonomy terms)、视图(views)等。你可以创建可打包(bundle)的实体,例如内容类型、区块类型、分类字典等。但如果你需要创建一个带有自己 bundle 的新实体类型怎么办?这种情况下,你就需要使用 Entity API 来创建新的实体类型。

我已将所有代码添加到 GitHub 上的 drupalbook_product 模块中,你可以下载该模块并将其添加到自己的网站中:

https://github.com/levmyshkin/drupalbook8

创建新的实体类型最简单的方法是通过 Drupal Console,因为只需要执行一个命令即可完成。

https://drupalconsole.com/

你并不需要频繁地创建新的实体类型。大多数中小型项目通常使用现有的贡献模块(contrib modules)作为基础,例如用于电子商务的 Commerce 模块:

https://www.drupal.org/project/commerce

如果你打算创建自己的插件模块,那么也许会需要定义新的实体类型。当然,你也可以在 Drupal 模块中找到功能相似的模块,然后为它们添加或扩展所缺少的功能。

在本文中,我们将学习 Entity API,并创建我们自己的 Product(产品)实体类型,它将作为一个小型自定义目录或商店的基础。如果你确实决定要创建自定义商店,我仍然强烈建议你使用 Commerce 模块,因为它可以为你和你的客户节省大量时间。

当你想创建一个新的实体类型时,可能会问:为什么不能直接创建一个新的“产品”内容类型(Content type)并用于目录?确实,对于一个带有 Views 输出、按价格或库存进行简单筛选的小型目录来说,这样做是可行的。但当产品数量达到上千时,管理员在内容页面查找产品会变得非常不便。管理员希望能在后台页面上使用按编号、分类、颜色、名称等的筛选功能:

/admin/content

这样会显得过于冗杂,并且干扰其他内容类型(如新闻、文章、活动、页面等)的管理。因此,在这种情况下,通常会创建一个单独的 Product 实体类型,并为其提供独立的后台面板和设置。

让我们开始创建一个单独的 Product 实体类型。在执行生成命令前,我强烈建议先为网站创建备份,至少备份数据库。因为创建实体类型的过程会生成配置文件(configs),这些文件会写入数据库,如果过程中出错、某些配置写入而实体文件缺失,可能会导致网站崩溃。因此请务必先创建备份。

现在我们来创建一个新模块。它同样可以通过 Drupal Console 生成:

drupal generate:module

https://hechoendrupal.gitbooks.io/drupal-console/en/commands/generate-module.html

$ vendor/bin/drupal generate:module
 
 // 欢迎使用 Drupal 模块生成器
 
 输入新模块名称:
 > Drupalbook Product
 
 输入模块机器名称 [drupalbook_product]:
 >
 
 输入模块路径 [modules/custom]:
 >
 
 输入模块描述 [My Awesome Module]:
 > Products catalog
 
 输入包名称 [Custom]:
 >
 
 输入 Drupal 核心版本 [8.x]:
 >
 
 是否生成 .module 文件?(yes/no) [yes]:
 > no
 
 定义模块为特性 (yes/no) [no]:
 > no
 
 是否添加 composer.json 文件?(yes/no) [yes]:
 > no
 
 是否添加模块依赖?(yes/no) [no]:
 > no
 
 是否生成单元测试类?(yes/no) [yes]:
 > no
 
 是否生成可主题化模板?(yes/no) [yes]:
 > no
 
 是否继续操作?(yes/no) [yes]:
 > yes
 
已生成或更新的文件
 生成路径: /home/laptop/projects/drupalbook
 1 - /modules/custom/drupalbook_product/drupalbook_product.info.yml
 
                                                                                                                         
 生成行数: "5"

或者手动创建一个模块文件 drupalbook_product.info.yml

name: 'drupalbook_product'
type: module
description: 'Products catalog'
core: 8.x
package: 'Drupalbook'

现在我们可以生成 Product 实体类型了。

https://hechoendrupal.gitbooks.io/drupal-console/en/commands/generate-entity-content.html

$ drupal generate:entity:content

$ vendor/bin/drupal generate:entity:content
 
 // 欢迎使用 Drupal 内容实体生成器
 输入模块名称 [admin_toolbar]:
 > drupalbook_product
 
 输入新实体类名称 [DefaultEntity]:
 > DrupalbookProductEntity
 
 输入新实体机器名称 [drupalbook_product_entity]:
 >
 
 输入新实体标签 [Drupalbook product entity]:
 > Product    
 
 输入实体路由基础路径 [/admin/structure]:
 >
 
 该实体是否具有 bundle?(yes/no) [no]:
 > yes
 
 实体是否支持多语言?(yes/no) [yes]:
 > yes
 
 实体是否可修订?(yes/no) [yes]:
 > no
 
 // generate:entity:config
 
 输入配置实体路由基础路径 [/admin/structure]:
 >
 
已生成或更新的文件
 生成路径: /home/laptop/projects/drupalbook
 ...(共生成 29 个文件,略)...
 生成行数: "1060"

模块生成后,启用它即可在网站上看到新的实体类型:

drupal console

在生成实体过程中,Drupal Console 会提示一些参数:

Enter the class of your new content entity [DefaultEntity]:
输入新实体的 PHP 类名,建议以 “Entity” 结尾。

Enter the machine name of your new content entity [drupalbook_product_entity]:
机器名称通常根据类名自动生成,直接按回车即可。

Enter the base-path for the content entity routes [/admin/structure]:
此路径决定实体 CRUD 操作的后台页面位置:

structure drupal 8

产品页面的默认显示方式较为简陋,但可以通过 Views 进行改进或重新设计:

Product display

要创建新实体,首先需要创建 Product 类型的 bundle。我们之前选择了可打包实体(bundable entity):

Do you want this (content) entity to have bundles? (yes/no):

因此,我们正在创建新的产品类型。这将用于定义不同的字段,例如重量、尺寸、颜色等属性。例如,显示器会有屏幕对角线尺寸字段,而鞋子则会有鞋码字段。

让我们创建一个新的产品类型——“Clothes(服装)”:

product type

现在,我们可以为新产品类型配置字段:

product type fields

至少要添加一个价格字段。

创建几个产品后,我们可以查看数据库。此时数据库中会有一个 drupalbook_product_entity 表,用于存储产品的 UUID:

product data

此外,还有一个 drupalbook_product_entity_field_data 表,用于存储实体的属性(Properties)。这些属性是直接保存在数据库表中的特殊字段,例如名称(Name,实体标签字段,例如节点标题 Title),它们不会随着修订而变化。

product entity

如果你添加了字段,则每个字段都会生成两张表,因为我们在创建时选择了可修订实体(revisionable entity):

Is your entity revisionable? (yes/no) [yes]

我想你现在已经明白如何创建新的实体类型了。在接下来的文章中,我们将扩展自定义目录/商店的功能。

我已将所有代码上传到 GitHub 的 drupalbook_product 模块中,你可以下载并将其添加到自己的网站:

https://github.com/levmyshkin/drupalbook8