update entity factory
This commit is contained in:
@@ -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<string, array<string, class-string<EntityParse>>>
|
||||
* @var array<int, array<string, class-string<EntityParse>>>
|
||||
*/
|
||||
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<EntityParse>
|
||||
* @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<EntityParse>|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<EntityParse> $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<string, array<string, class-string<EntityParse>>> $mappings
|
||||
* @param array<int, array<string, class-string<EntityParse>>> $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<string, array<string, class-string<EntityParse>>>
|
||||
* @return array<int, array<string, class-string<EntityParse>>>
|
||||
*/
|
||||
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]['*']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* EntityParse 配置文件
|
||||
*
|
||||
* 用于手动注册平台与 Parser 的映射关系
|
||||
* 如果不配置,工厂会根据命名约定自动查找 Parser 类
|
||||
*
|
||||
* 配置格式:
|
||||
* [
|
||||
* platform_id => [
|
||||
* '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,
|
||||
// ],
|
||||
],
|
||||
];
|
||||
Reference in New Issue
Block a user