amcgowanca / discoverable_entity_bundle_classes
实现特定包的实体类的实验性方法。
Requires
- amcgowanca/entity_utilities: dev-8.x-1.x
This package is auto-updated.
Last update: 2024-09-26 17:15:49 UTC
README
目前,在Drupal 8中,没有机制可以在每个包的基础上通过唯一的类类型推导基础实体类型的类实现。因此,如果重写实体类型类,该类类型将被用于将该实体实例化的所有实例。
此模块也称为“DEBC”,即“可发现实体包类”。
安装与使用
通过Composer安装
应通过使用Composer安装此模块。
$ composer require amcgowanca/discoverable_entity_bundle_classes:^1.0
使用
Discoverable Entity Bundle Classes模块不提供任何“即用型”的设置或配置,并且专注于提高开发人员构建优雅解决方案的体验。因此,需要以下内容
-
确保您希望为其创建实体包类的实体类型的存储类实现了
Drupal\discoverable_entity_bundle_classes\Storage\SqlContentEntityStorageTrait
特性。此特性的实现侧重于确保有效地覆盖Drupal核心中所需的SqlContentEntityStorage
类方法,以允许发现包类及其实例化。请注意,此模块提供了Drupal核心的节点、评论和分类术语实体所需的存储类表示,但并未激活它们。这有意留给实施项目的技术架构师来决定。请参阅下文第2点。
-
如果实体类型(例如节点)是通过Drupal核心或贡献模块包提供的,请确保存在或提供实现了所需
SqlContentEntityStorageTrait
特性的存储类。通过使用hook_entity_type_alter(&$entity_types)
覆盖实体类型的存储类。/** * Implements hook_entity_type_alter(&$entity_types) */ function my_module_entity_type_alter(&$entity_types) { /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */ if (isset($entity_types['node'])) { $entity_types['node']->setStorageClass('\Drupal\discoverable_entity_bundle_classes\Storage\Node\NodeStorage'); } }
-
定义自定义实体包类(例如文章),该类扩展了先前定义的基础实体类。例如,如果文章是节点的一种类型,则应定义如下
namespace Drupal\my_module\Entity; use Drupal\node\Entity\Node; class Article extends Node implements ArticleInterface { ... }
-
任何特定包的类必须也实现接口,
ContentEntityBundleInterface
。namespace Drupal\my_module\Entity; use Drupal\node\Entity\Node; use Drupal\discoverable_entity_bundle_classes\ContentEntityBundleInterface; class Article extends Node implements ArticleInterface, ContentEntityBundleInterface { ... }
-
特定包的类必须还用
@ContentEntityBundleClass
注释,该注释定义以下属性label
:实体包类的可读性表示(例如,@Translation("Article")
)entity_type
:基础实体类型(例如,node
)。bundle
:此类应应用的实体包。
namespace Drupal\my_module\Entity; use Drupal\node\Entity\Node; use Drupal\discoverable_entity_bundle_classes\ContentEntityBundleInterface; /** * Defines an Article node class. * * @ContentEntityBundleClass( * label = @Translation("Article"), * entity_type = "node", * bundle = "article" * ); */ class Article extends Node implements ArticleInterface, ContentEntityBundleInterface { ... }
-
最后,清除缓存(
drush @site.alias cache-rebuild
),并开始创建出色的Drupal解决方案。
此项目的历史记录
开始
此模块和架构方法最初是为一个全球品牌而设计的。目的是允许一个简单的概念证明,使能够推导实体类(例如\Drupal\node\Entity\Node
)的专门实现。目标是实现一层抽象和去耦常见的Drupal特性,以实现服务和其他数据管理器仅根据定义的接口(而不是Drupal的数据表示)操作。
快进+1年
本模块已广泛应用于小型非营利组织到《财富》100强企业,通过使交付团队能够构建优雅的软件,这些软件不受常见Drupal实现紧密耦合行为的影响。
在Drupal.org上
以下链接指向Drupal.org问题,这些问题引用了这个特定项目 以及 作为其架构的一部分,该项目解决这些问题。
实际案例
事实上,项目被Drupal特有的行为淹没是很常见的情况,尤其是在项目的开发周期早期看似易于管理,但随着时间的推移却变得难以管理——更不用说在其第一次生产发布之后。
使多个数据点“可定位”
场景:一个单一的项目有多种数据类型——一个节点类型 和 词汇表,代表一个单一的“位置”。由于重复的性质,词汇表的实现来自原始交付团队,仅用于内容的分类。节点类型“位置”是事后考虑的,因此仅用于
- 表示用于内容创建的“页面”位置,
- (未来需求)对新内容类型的分类以及最终的历史实现,用于构建关系型内容模型。
问题:如何在不引入大量努力的情况下维护大型代码库,同时保持功能业务逻辑的持久性,引入或最终删除数据类型。
答案:通过在数据类型(例如,节点 或 词汇表)和服务或其他使用强类型参数的类实现之间建立良好的抽象。
观察到的变化:通过最小化核心业务逻辑和类实现的重构,这个特定项目能够通过利用DEBC和由实体包类实现的良好定义的接口来减少Drupal特有的行为。
代码减少和类型提示值的示例允许
之前:
之后:
许可
此Drupal模块根据GNU通用公共许可证版本2进行许可。