entityMatch($message); * $rawData = json_decode($message->getBody(), true); * $entity = $parser->entityMap($rawData, $entity); * $entity->save(); * * // 指定实体类型(覆盖自动提取) * $parser = EntityParseFactory::createFromMessage($message, 'order'); * * 命名约定(推荐方式): * - 创建符合命名约定的 Parser 类,工厂自动查找 * - 类名:{Platform}{Entity}Parser * - 命名空间:App\Platform\{Platform} * - 示例:App\Platform\Tmall\TmallOrderParser * * 查找顺序: * 1. App\Platform\Tmall\TmallOrderParser * 2. App\Platform\Tmall\OrderParser * 3. App\Platform\TmallOrderParser * * 如果找不到对应的 Parser 类,将抛出 InvalidArgumentException * * 配置文件(可选): * - 如需覆盖默认行为,可在 config/autoload/entity_parse.php 中配置 * - 支持通配符 '*' 匹配所有实体类型 */ class EntityParseFactory { /** * 平台与 Parser 类的映射表 * 格式:['platform_name' => ['entity_type' => ParserClass]] * * @var array>> */ private static array $registry = []; /** * 容器实例 */ private static ?ContainerInterface $container = null; /** * 配置实例 */ private static ?ConfigInterface $config = null; /** * 设置容器(由框架注入) * * @param ContainerInterface $container * @return void */ public static function setContainer(ContainerInterface $container): void { self::$container = $container; self::$config = $container->get(ConfigInterface::class); self::loadConfig(); } /** * 从配置文件加载平台映射 * * @return void */ private static function loadConfig(): void { if (!self::$config) { return; } $parsers = self::$config->get('entity_parse.platforms', []); foreach ($parsers as $platform => $entities) { foreach ($entities as $entityType => $parserClass) { self::register($platform, $entityType, $parserClass); } } } /** * 根据消息自动创建 Parser 实例(静态方法) * * @param AMQPMessage $message * @param string|null $entityType 实体类型(可选,如果不指定则从 payload 中提取) * @return EntityParseInterface * @throws InvalidArgumentException */ public static function createFromMessage( AMQPMessage $message, ?string $entityType = null ): EntityParseInterface { // 1. 从消息体中解析数据 $data = json_decode($message->getBody(), true); if (!is_array($data)) { throw new InvalidArgumentException('Invalid message body: expected JSON array'); } // 2. 从 data 中提取平台名称 $platformName = self::extractPlatformNameFromData($data); // 3. 如果未指定实体类型,从 data 或 routing key 中提取 if ($entityType === null) { $entityType = self::extractEntityTypeFromData($data, $message); } // 4. 获取对应的 Parser 类 $parserClass = self::resolveParserClass($platformName, $entityType); // 5. 创建并返回 Parser 实例,传递解析后的数据 return $parserClass::create($data); } /** * 从数据中提取平台名称(从 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 * @return string */ private static function extractEntityTypeFromData(array $data, AMQPMessage $message): string { // 优先从 routing key 中提取 $routingKey = $message->getRoutingKey(); $entityType = Str::of($routingKey) ->before('.') ->lower() ->toString(); if (!empty($entityType)) { return $entityType; } throw new InvalidArgumentException("Cannot extract entity type from routing key: {$routingKey}"); } /** * 解析 Parser 类名 * * 优先级: * 1. 手动注册的映射 * 2. 配置文件中的映射 * 3. 命名约定自动查找 * * @param string $platformName * @param string $entityType * @return class-string * @throws InvalidArgumentException */ private static function resolveParserClass(string $platformName, string $entityType): string { // 1. 检查手动注册的映射 if (isset(self::$registry[$platformName][$entityType])) { return self::$registry[$platformName][$entityType]; } // 2. 检查通配符映射(支持 * 匹配所有实体类型) if (isset(self::$registry[$platformName]['*'])) { return self::$registry[$platformName]['*']; } // 3. 使用命名约定自动查找 $parserClass = self::findByConvention($platformName, $entityType); if ($parserClass) { // 自动注册以提高后续性能 self::register($platformName, $entityType, $parserClass); return $parserClass; } throw new InvalidArgumentException( "Cannot find parser for platform '{$platformName}' and entity '{$entityType}'. " . "Please register it using EntityParseFactory::register() or create a parser class following the naming convention." ); } /** * 根据命名约定查找 Parser 类 * * 命名约定: * - 类名:{Entity} * - 命名空间:App\Platform\{Platform}\EntityParse * * 示例: * - Platform: shopee, Entity: order -> App\Platform\Shopee\EntityParse\Order * - Platform: tmall, Entity: product -> App\Platform\Tmall\EntityParse\Product * * @param string $platformName * @param string $entityType * @return class-string|null */ private static function findByConvention(string $platformName, string $entityType): ?string { // 构建类名 $platformPascal = Str::of($platformName)->ucfirst()->toString(); $entityPascal = Str::of($entityType)->ucfirst()->toString(); // 标准命名:App\Platform\Shopee\EntityParse\Order $class = "App\\Platform\\{$platformPascal}\\EntityParse\\{$entityPascal}"; if (class_exists($class) && is_subclass_of($class, EntityParse::class)) { return $class; } return null; } /** * 手动注册平台与 Parser 的映射关系 * * @param string $platformName 平台名称(小写) * @param string $entityType 实体类型(小写),使用 '*' 表示匹配所有实体类型 * @param class-string $parserClass Parser 类名 * @return void * @throws InvalidArgumentException */ public static function register(string $platformName, string $entityType, string $parserClass): void { // 验证 Parser 类是否存在 if (!class_exists($parserClass)) { throw new InvalidArgumentException("Parser class '{$parserClass}' does not exist"); } // 验证 Parser 类是否继承自 EntityParse if (!is_subclass_of($parserClass, EntityParse::class)) { throw new InvalidArgumentException( "Parser class '{$parserClass}' must extend " . EntityParse::class ); } // 注册映射 self::$registry[$platformName][$entityType] = $parserClass; } /** * 批量注册平台映射 * * @param array>> $mappings * @return void */ public static function registerBatch(array $mappings): void { foreach ($mappings as $platform => $entities) { foreach ($entities as $entityType => $parserClass) { self::register($platform, $entityType, $parserClass); } } } /** * 获取所有已注册的映射 * * @return array>> */ public static function getRegistry(): array { return self::$registry; } /** * 清空所有注册的映射(主要用于测试) * * @return void */ public static function clearRegistry(): void { self::$registry = []; } /** * 检查指定平台和实体类型的 Parser 是否已注册 * * @param string $platformName * @param string $entityType * @return bool */ public static function hasParser(string $platformName, string $entityType): bool { return isset(self::$registry[$platformName][$entityType]) || isset(self::$registry[$platformName]['*']); } }