Skip to Content
🚀 Drubase One v1.1 - 基于 Drupal 11 的多租户后端即服务平台
Docs模块BaaS Entity

BaaS Entity 模块

动态实体管理模块 - 实现运行时数据模型定义和 CRUD 操作。

📦 模块信息

  • 依赖: baas_tenant, baas_project
  • 位置: web/modules/custom/baas_entity/

🏗️ 架构设计

核心概念

动态实体(Dynamic Entity)是 BaaS 平台的数据模型核心:

  • 运行时定义数据结构
  • 自动生成数据表和 Entity 类
  • 支持多种字段类型
  • 项目级数据隔离

数据库表

baas_entity_template - 实体模板

CREATE TABLE baas_entity_template ( template_id SERIAL PRIMARY KEY, project_id VARCHAR(255) NOT NULL, entity_name VARCHAR(255) NOT NULL, label VARCHAR(255), description TEXT, created INTEGER, updated INTEGER );

baas_entity_field - 实体字段

CREATE TABLE baas_entity_field ( field_id SERIAL PRIMARY KEY, template_id INTEGER NOT NULL, field_name VARCHAR(255) NOT NULL, field_type VARCHAR(50) NOT NULL, label VARCHAR(255), required BOOLEAN DEFAULT FALSE, settings TEXT );

🔧 主要类和方法

EntityTemplateManager

实体模板管理 - src/Service/EntityTemplateManager.php

// 创建实体模板 public function createTemplate(array $template_data): int // 添加字段 public function addField(int $template_id, array $field_data): int // 获取模板 public function getTemplate(int $template_id): ?array // 生成实体类文件 public function generateEntityClasses(int $template_id): bool

DynamicEntityService

实体 CRUD 操作 - src/Service/DynamicEntityService.php

// 创建实体记录 public function create(string $entity_name, array $data): int // 查询实体列表 public function query(string $entity_name, array $conditions = []): array // 更新实体 public function update(string $entity_name, int $id, array $data): bool // 删除实体 public function delete(string $entity_name, int $id): bool

ProjectTableNameGenerator

表名生成服务 - src/Service/ProjectTableNameGenerator.php

// 生成表名 public function generateTableName( string $tenant_id, string $project_id, string $entity_name ): string // 示例: baas_856064_users // 856064 = MD5(tenant_id + project_id) 前6位

📂 动态实体文件生成

概述

当创建实体模板时,系统会自动生成两个 PHP 类文件:Entity 类Storage 类。这些文件存储在 web/sites/default/files/dynamic_entities/ 目录中,遵循租户和项目的层级结构。

生成目的

  1. Drupal 标准兼容 - 生成的类继承自 Drupal 核心的 ContentEntityBaseSqlContentEntityStorage
  2. 数据隔离 - 每个类内置租户ID和项目ID常量,确保数据查询的隔离性
  3. 自动注册 - 通过 ProjectEntityRegistry 服务动态注册到 Drupal 实体系统
  4. 类型安全 - 提供类型提示和IDE自动补全支持

目录结构

dynamic_entities/ └── {tenant_hash}/ # 租户哈希 (如: 7375b0cd) └── projects/ └── {tenant_hash}_{project_hash}/ # 项目哈希 (如: 7375b0cd_6888d012be80c) ├── Entity/ # 实体类目录 │ ├── Project{Hash}Users.php # 用户实体类 │ ├── Project{Hash}Activities.php # 活动实体类 │ ├── Project{Hash}Teams.php # 团队实体类 │ ├── Project{Hash}Positions.php # 位置实体类 │ ├── Project{Hash}UserActivities.php # 用户活动关联类 │ └── Project{Hash}SystemConfig.php # 系统配置类 └── Storage/ # 存储类目录 ├── Project{Hash}UsersStorage.php ├── Project{Hash}ActivitiesStorage.php ├── Project{Hash}TeamsStorage.php ├── Project{Hash}PositionsStorage.php ├── Project{Hash}UserActivitiesStorage.php └── Project{Hash}SystemConfigStorage.php

示例: Groups 项目 (tenant_7375b0cd_project_6888d012be80c) 的实体文件

  • 租户哈希: 7375b0cd
  • 项目哈希: 7375b0cd_6888d012be80c
  • 类名前缀: Project7375b0cd6888d012be80c
  • 数据表名: baas_856064_users (856064 = MD5 前6位)

Entity 类结构

namespace Drupal\baas_project\Entity\Dynamic; use Drupal\Core\Entity\ContentEntityBase; /** * 定义项目级动态实体类: users. * * 此文件由BaaS项目系统自动生成。 * 生成时间: 2025-10-11 22:40:14 * 表名: baas_856064_users * 实体类型ID: baas_856064_users */ class Project7375b0cd6888d012be80cUsers extends ContentEntityBase { const TENANT_ID = '7375b0cd'; const PROJECT_ID = '7375b0cd_6888d012be80c'; const ENTITY_NAME = 'users'; // 自动注入租户和项目ID public function __construct(array $values = [], ...) { parent::__construct($values, 'baas_856064_users', NULL, ...); $this->set('tenant_id', self::TENANT_ID); $this->set('project_id', self::PROJECT_ID); } // 定义基础字段(id, uuid, tenant_id, project_id等) public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { // ... } }

Storage 类结构

namespace Drupal\baas_project\Storage\Dynamic; use Drupal\Core\Entity\Sql\SqlContentEntityStorage; /** * 项目级动态实体存储类: users. */ class Project7375b0cd6888d012be80cUsersStorage extends SqlContentEntityStorage { const TENANT_ID = '7375b0cd'; const PROJECT_ID = '7375b0cd_6888d012be80c'; const ENTITY_NAME = 'users'; // 确保查询时自动过滤租户和项目 public function loadByProperties(array $values = []) { $values['tenant_id'] = self::TENANT_ID; $values['project_id'] = self::PROJECT_ID; return parent::loadByProperties($values); } }

生成流程

关键特性

  1. 自动化生成 - 无需手动编写实体类代码
  2. 命名空间隔离 - 使用项目哈希值确保类名唯一性
  3. 数据隔离保证 - 内置常量和自动过滤确保多租户安全
  4. 动态注册 - 无需重启服务,实时生效
  5. 标准兼容 - 完全遵循 Drupal Entity API 规范

EntityDataApiController

实体 API 控制器 - src/Controller/EntityDataApiController.php

// GET /api/v1/{tenant_id}/projects/{project_id}/entities/{entity_name} public function listEntities(Request $request): JsonResponse // POST /api/v1/{tenant_id}/projects/{project_id}/entities/{entity_name} public function createEntity(Request $request): JsonResponse // PUT /api/v1/{tenant_id}/projects/{project_id}/entities/{entity_name}/{id} public function updateEntity(Request $request, int $id): JsonResponse

📖 使用示例

创建实体模板

$template_manager = \Drupal::service('baas_entity.template_manager'); // 创建用户实体模板 $template_id = $template_manager->createTemplate([ 'project_id' => 'tenant_7375b0cd_project_6888d012be80c', 'entity_name' => 'users', 'label' => '用户', 'description' => '用户实体', ]); // 添加字段 $template_manager->addField($template_id, [ 'field_name' => 'name', 'field_type' => 'string', 'label' => '姓名', 'required' => true, ]); $template_manager->addField($template_id, [ 'field_name' => 'email', 'field_type' => 'string', 'label' => '邮箱', 'required' => true, ]);

CRUD 操作

$entity_service = \Drupal::service('baas_entity.dynamic_entity'); // 创建 $id = $entity_service->create('users', [ 'name' => '张三', 'email' => 'zhangsan@example.com', ]); // 查询 $users = $entity_service->query('users', [ 'status' => 'active', ]); // 更新 $entity_service->update('users', $id, [ 'name' => '张三(已更新)', ]); // 删除 $entity_service->delete('users', $id);

🔌 服务注册

baas_entity.services.yml:

services: baas_entity.template_manager: class: Drupal\baas_entity\Service\EntityTemplateManager arguments: - '@database' - '@baas_project.table_name_generator' baas_entity.dynamic_entity: class: Drupal\baas_entity\Service\DynamicEntityService arguments: - '@database' - '@baas_entity.template_manager' baas_project.table_name_generator: class: Drupal\baas_entity\Service\ProjectTableNameGenerator

🔗 相关文档

Last updated on