From 4ca0fcadeb9355ff21520ca471710380b6f4569f Mon Sep 17 00:00:00 2001 From: Nick Zeng Date: Mon, 15 Dec 2025 15:47:56 +0800 Subject: [PATCH] update entity factory --- .../app/Entity/Parse/EntityParseFactory.php | 138 ++++++++---------- backend/config/autoload/entity_parse.php | 48 ++++++ 2 files changed, 105 insertions(+), 81 deletions(-) create mode 100644 backend/config/autoload/entity_parse.php diff --git a/backend/app/Entity/Parse/EntityParseFactory.php b/backend/app/Entity/Parse/EntityParseFactory.php index d995b7e..56019ac 100644 --- a/backend/app/Entity/Parse/EntityParseFactory.php +++ b/backend/app/Entity/Parse/EntityParseFactory.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace App\Entity\Parse; +use App\Model\Platform; use Hyperf\Amqp\Message\ConsumerMessageInterface; use Hyperf\Contract\ConfigInterface; use Hyperf\Stringable\Str; @@ -32,28 +33,29 @@ use PhpAmqpLib\Message\AMQPMessage; * * 命名约定(推荐方式): * - 创建符合命名约定的 Parser 类,工厂自动查找 - * - 类名:{Platform}{Entity}Parser - * - 命名空间:App\Platform\{Platform} - * - 示例:App\Platform\Tmall\TmallOrderParser + * - 类名:{Entity} + * - 命名空间:App\Platform\{Platform}\EntityParse + * - 示例:App\Platform\Shopee\EntityParse\Order * - * 查找顺序: - * 1. App\Platform\Tmall\TmallOrderParser - * 2. App\Platform\Tmall\OrderParser - * 3. App\Platform\TmallOrderParser + * 平台名称来源: + * - 从 platforms 表中根据 platform_id 查询 name 字段 + * - 示例:platform_id=25 -> name='Shopee' -> App\Platform\Shopee\EntityParse\Order * * 如果找不到对应的 Parser 类,将抛出 InvalidArgumentException * * 配置文件(可选): * - 如需覆盖默认行为,可在 config/autoload/entity_parse.php 中配置 + * - 配置格式:[platform_id => ['entity_type' => ParserClass]] * - 支持通配符 '*' 匹配所有实体类型 */ class EntityParseFactory { /** * 平台与 Parser 类的映射表 - * 格式:['platform_name' => ['entity_type' => ParserClass]] + * 格式:[platform_id => ['entity_type' => ParserClass]] + * 示例:[25 => ['order' => ShopeeOrderParser, 'product' => ShopeeProductParser]] * - * @var array>> + * @var array>> */ private static array $registry = []; @@ -119,63 +121,26 @@ class EntityParseFactory throw new InvalidArgumentException('Invalid message body: expected JSON array'); } - // 2. 从 data 中提取平台名称 - $platformName = self::extractPlatformNameFromData($data); + // 2. 从 data 中提取 platform_id + if (!isset($data['platform_id'])) { + throw new InvalidArgumentException('Missing required field: platform_id'); + } + $platformId = (int) $data['platform_id']; - // 3. 如果未指定实体类型,从 data 或 routing key 中提取 + // 3. 如果未指定实体类型,从 routing key 中提取 if ($entityType === null) { $entityType = self::extractEntityTypeFromData($data, $message); } // 4. 获取对应的 Parser 类 - $parserClass = self::resolveParserClass($platformName, $entityType); + $parserClass = self::resolveParserClass($platformId, $entityType); // 5. 创建并返回 Parser 实例,传递解析后的数据和消息对象 return $parserClass::create($data, $message); } /** - * 从数据中提取平台名称(从 meta 字段中获取) - * - * @param array $data - * @return string - * @throws InvalidArgumentException - */ - private static function extractPlatformNameFromData(array $data): string - { - if (!isset($data['meta']['platform_id'])) { - throw new InvalidArgumentException("Cannot extract platform name from data: meta.platform_id missing"); - } - - return self::resolvePlatformName($data['meta']['platform_id']); - } - - /** - * 根据 platform_id 解析平台名称 - * - * @param mixed $platformId - * @return string - */ - private static function resolvePlatformName($platformId): string - { - // TODO: 从配置或数据库中根据 platform_id 查找平台名称 - // 临时方案:使用简单的映射 - $platformMap = [ - 1 => 'taobao', - 2 => 'tmall', - 3 => 'jd', - // ... 其他平台 - ]; - - if (isset($platformMap[$platformId])) { - return $platformMap[$platformId]; - } - - throw new InvalidArgumentException("Unknown platform_id: {$platformId}"); - } - - /** - * 从数据或路由键中提取实体类型 + * 从路由键中提取实体类型 * * @param array $data * @param AMQPMessage $message @@ -206,34 +171,34 @@ class EntityParseFactory * 2. 配置文件中的映射 * 3. 命名约定自动查找 * - * @param string $platformName + * @param int $platformId * @param string $entityType * @return class-string * @throws InvalidArgumentException */ - private static function resolveParserClass(string $platformName, string $entityType): string + private static function resolveParserClass(int $platformId, string $entityType): string { // 1. 检查手动注册的映射 - if (isset(self::$registry[$platformName][$entityType])) { - return self::$registry[$platformName][$entityType]; + if (isset(self::$registry[$platformId][$entityType])) { + return self::$registry[$platformId][$entityType]; } // 2. 检查通配符映射(支持 * 匹配所有实体类型) - if (isset(self::$registry[$platformName]['*'])) { - return self::$registry[$platformName]['*']; + if (isset(self::$registry[$platformId]['*'])) { + return self::$registry[$platformId]['*']; } // 3. 使用命名约定自动查找 - $parserClass = self::findByConvention($platformName, $entityType); + $parserClass = self::findByConvention($platformId, $entityType); if ($parserClass) { // 自动注册以提高后续性能 - self::register($platformName, $entityType, $parserClass); + self::register($platformId, $entityType, $parserClass); return $parserClass; } throw new InvalidArgumentException( - "Cannot find parser for platform '{$platformName}' and entity '{$entityType}'. " . + "Cannot find parser for platform_id '{$platformId}' and entity '{$entityType}'. " . "Please register it using EntityParseFactory::register() or create a parser class following the naming convention." ); } @@ -246,18 +211,29 @@ class EntityParseFactory * - 命名空间:App\Platform\{Platform}\EntityParse * * 示例: - * - Platform: shopee, Entity: order -> App\Platform\Shopee\EntityParse\Order - * - Platform: tmall, Entity: product -> App\Platform\Tmall\EntityParse\Product + * - platform_id: 25 (Shopee), entity: order -> App\Platform\Shopee\EntityParse\Order + * - platform_id: 2 (Tmall), entity: product -> App\Platform\Tmall\EntityParse\Product * - * @param string $platformName + * @param int $platformId * @param string $entityType * @return class-string|null */ - private static function findByConvention(string $platformName, string $entityType): ?string + private static function findByConvention(int $platformId, string $entityType): ?string { - // 构建类名 - $platformPascal = Str::of($platformName)->ucfirst()->toString(); - $entityPascal = Str::of($entityType)->ucfirst()->toString(); + // 从数据库查询平台信息 + $platform = Platform::find($platformId); + + if (!$platform || !isset($platform->name)) { + return null; + } + + // 使用平台名称构建类名(处理多词平台名,如 "Amazon Japan" -> "AmazonJapan") + $platformPascal = Str::of($platform->name) + ->replace(' ', '') // 移除空格 + ->studly() // 转换为 StudlyCase + ->toString(); + + $entityPascal = Str::of($entityType)->studly()->toString(); // 标准命名:App\Platform\Shopee\EntityParse\Order $class = "App\\Platform\\{$platformPascal}\\EntityParse\\{$entityPascal}"; @@ -272,13 +248,13 @@ class EntityParseFactory /** * 手动注册平台与 Parser 的映射关系 * - * @param string $platformName 平台名称(小写) + * @param int $platformId 平台 ID(如:25 表示 Shopee) * @param string $entityType 实体类型(小写),使用 '*' 表示匹配所有实体类型 * @param class-string $parserClass Parser 类名 * @return void * @throws InvalidArgumentException */ - public static function register(string $platformName, string $entityType, string $parserClass): void + public static function register(int $platformId, string $entityType, string $parserClass): void { // 验证 Parser 类是否存在 if (!class_exists($parserClass)) { @@ -293,20 +269,20 @@ class EntityParseFactory } // 注册映射 - self::$registry[$platformName][$entityType] = $parserClass; + self::$registry[$platformId][$entityType] = $parserClass; } /** * 批量注册平台映射 * - * @param array>> $mappings + * @param array>> $mappings * @return void */ public static function registerBatch(array $mappings): void { - foreach ($mappings as $platform => $entities) { + foreach ($mappings as $platformId => $entities) { foreach ($entities as $entityType => $parserClass) { - self::register($platform, $entityType, $parserClass); + self::register($platformId, $entityType, $parserClass); } } } @@ -314,7 +290,7 @@ class EntityParseFactory /** * 获取所有已注册的映射 * - * @return array>> + * @return array>> */ public static function getRegistry(): array { @@ -334,13 +310,13 @@ class EntityParseFactory /** * 检查指定平台和实体类型的 Parser 是否已注册 * - * @param string $platformName + * @param int $platformId * @param string $entityType * @return bool */ - public static function hasParser(string $platformName, string $entityType): bool + public static function hasParser(int $platformId, string $entityType): bool { - return isset(self::$registry[$platformName][$entityType]) - || isset(self::$registry[$platformName]['*']); + return isset(self::$registry[$platformId][$entityType]) + || isset(self::$registry[$platformId]['*']); } } diff --git a/backend/config/autoload/entity_parse.php b/backend/config/autoload/entity_parse.php new file mode 100644 index 0000000..80d2f5f --- /dev/null +++ b/backend/config/autoload/entity_parse.php @@ -0,0 +1,48 @@ + [ + * 'entity_type' => ParserClass, + * ... + * ], + * ... + * ] + * + * 示例: + * [ + * 25 => [ // Shopee (platform_id = 25) + * 'order' => \App\Platform\Shopee\EntityParse\Order::class, + * 'product' => \App\Platform\Shopee\EntityParse\Product::class, + * ], + * 2 => [ // Tmall (platform_id = 2) + * '*' => \App\Platform\Tmall\EntityParse\Universal::class, // 通配符:匹配所有实体类型 + * ], + * ] + * + * 平台 ID 参考(来自 platforms 表): + * - 1: JD + * - 2: Tmall + * - 25: Shopee + * - 18: LAZADA + * - 20: DouYin + * 更多平台 ID 请查看数据库 platforms 表 + */ + +return [ + 'platforms' => [ + // 示例配置(默认为空,使用命名约定自动查找) + // 25 => [ + // 'order' => \App\Platform\Shopee\EntityParse\Order::class, + // 'product' => \App\Platform\Shopee\EntityParse\Product::class, + // ], + ], +];