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 ConsumerMessageInterface $message * @param string|null $entityType 实体类型(可选,如果不指定则从 routing key 中提取) * @return EntityParseInterface * @throws InvalidArgumentException */ public static function createFromMessage( ConsumerMessageInterface $message, ?string $entityType = null ): EntityParseInterface { // 1. 从 exchange 中提取平台名称 $platformName = self::extractPlatformName($message); // 2. 如果未指定实体类型,从 routing key 中提取 if ($entityType === null) { $entityType = self::extractEntityType($message); } // 3. 获取对应的 Parser 类 $parserClass = self::resolveParserClass($platformName, $entityType); // 4. 创建并返回 Parser 实例 return $parserClass::create($message); } /** * 从 exchange 中提取平台名称 * * 规则:exchange 格式为 "platform.exchange" * 例如:tmall.exchange -> tmall * * @param ConsumerMessageInterface $message * @return string */ private static function extractPlatformName(ConsumerMessageInterface $message): string { $exchange = $message->getExchange(); $platformName = Str::of($exchange) ->before('.') ->lower() ->toString(); if (empty($platformName)) { throw new InvalidArgumentException("Cannot extract platform name from exchange: {$exchange}"); } return $platformName; } /** * 从 routing key 中提取实体类型 * * 规则:routing key 格式为 "entity.action" * 例如:order.create -> order * * @param ConsumerMessageInterface $message * @return string */ private static function extractEntityType(ConsumerMessageInterface $message): string { $routingKey = $message->getRoutingKey(); $entityType = Str::of($routingKey) ->before('.') ->lower() ->toString(); if (empty($entityType)) { throw new InvalidArgumentException("Cannot extract entity type from routing key: {$routingKey}"); } return $entityType; } /** * 解析 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 类 * * 命名约定: * 1. 类名:{Platform}{Entity}Parser * 2. 命名空间:App\Platform\{Platform} * * 示例: * - Platform: tmall, Entity: order -> App\Platform\Tmall\TmallOrderParser * - Platform: shopee, Entity: product -> App\Platform\Shopee\ShopeeProductParser * * @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(); // 尝试的类名列表 $possibleClasses = [ // App\Platform\Tmall\TmallOrderParser "App\\Platform\\{$platformPascal}\\{$platformPascal}{$entityPascal}Parser", // App\Platform\Tmall\OrderParser "App\\Platform\\{$platformPascal}\\{$entityPascal}Parser", // App\Platform\TmallOrderParser "App\\Platform\\{$platformPascal}{$entityPascal}Parser", ]; foreach ($possibleClasses as $class) { if (class_exists($class)) { // 验证类是否继承自 EntityParse if (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]['*']); } }