Files
datahub/backend/app/Entity/Parse/EntityParse.php
T

270 lines
7.0 KiB
PHP
Raw Normal View History

2025-11-27 13:40:58 +08:00
<?php
declare(strict_types=1);
namespace App\Entity\Parse;
use App\Model\Model as Entity;
use App\Model\Company;
use App\Model\Platform;
use App\Model\Store;
use App\Entity\Parse\Traits\EntityParseHelper;
2025-12-11 16:38:29 +08:00
use Hyperf\Amqp\Message\ConsumerMessageInterface;
2025-11-27 15:03:25 +08:00
use Hyperf\Collection\LazyCollection;
2025-11-27 13:40:58 +08:00
use InvalidArgumentException;
/**
* EntityParse 抽象类
*
* 使用工厂方法模式 + 延迟初始化
* 提供消息解析的通用框架和默认实现
*
2025-12-11 16:38:29 +08:00
* @method static static create(array $data, ConsumerMessageInterface $message)
2025-11-27 13:40:58 +08:00
*/
abstract class EntityParse implements EntityParseInterface
{
use EntityParseHelper;
2025-11-27 15:03:25 +08:00
protected array $data;
2025-12-11 16:38:29 +08:00
protected ConsumerMessageInterface $message;
2025-11-27 13:40:58 +08:00
protected ?Platform $platform = null;
protected ?Company $company = null;
protected ?Store $store = null;
/**
* 禁止直接使用构造函数
* 使用 create() 工厂方法创建实例
*/
protected function __construct()
{
// 空构造函数,延迟初始化
}
/**
* 工厂方法:创建解析器实例
*
2025-11-27 15:03:25 +08:00
* @param array $data
2025-12-11 16:38:29 +08:00
* @param ConsumerMessageInterface $message
2025-11-27 13:40:58 +08:00
* @return static
* @throws InvalidArgumentException
*/
2025-12-11 16:38:29 +08:00
public static function create(array $data, ConsumerMessageInterface $message): static
2025-11-27 13:40:58 +08:00
{
$instance = new static();
2025-11-27 15:03:25 +08:00
$instance->data = $data;
2025-12-11 16:38:29 +08:00
$instance->message = $message;
2025-11-27 15:03:25 +08:00
// 在初始化前先验证数据
if (!$instance->messageValidate($data)) {
throw new InvalidArgumentException('Message validation failed: required fields missing');
}
2025-11-27 13:40:58 +08:00
$instance->initialize();
return $instance;
}
2025-11-27 15:03:25 +08:00
/**
* 消息数据验证
*
* 默认实现:验证必需字段
* 子类可以覆写以添加自定义验证逻辑
*
* @param array $data
* @return bool
*/
public function messageValidate(array $data): bool
{
// 验证必需字段
$requiredFields = ['company_id', 'platform_id', 'store_id', 'unique_id', 'raw_data'];
foreach ($requiredFields as $field) {
if (!isset($data[$field])) {
return false;
}
}
return true;
}
2025-11-27 13:40:58 +08:00
/**
* 延迟初始化
2025-11-27 15:03:25 +08:00
* 在 data 设置后执行作用域匹配和验证
2025-11-27 13:40:58 +08:00
*
* @return void
* @throws InvalidArgumentException
*/
protected function initialize(): void
{
2025-11-27 15:03:25 +08:00
// 提取 metadata
$metadata = [
'company_id' => $this->data['company_id'],
'platform_id' => $this->data['platform_id'],
'store_id' => $this->data['store_id'],
'unique_id' => $this->data['unique_id'],
];
$this->platform = $this->platformScopeMatch($metadata);
$this->company = $this->companyScopeMatch($metadata);
$this->store = $this->storeScopeMatch($metadata);
2025-11-27 13:40:58 +08:00
$this->validateScope();
}
/**
* 验证作用域对象是否有效
*
* @return void
* @throws InvalidArgumentException
*/
protected function validateScope(): void
{
if (!$this->platform instanceof Platform || !isset($this->platform->id)) {
throw new InvalidArgumentException('Platform is undefined or invalid');
}
if (!$this->company instanceof Company || !isset($this->company->id)) {
throw new InvalidArgumentException('Company is undefined or invalid');
}
if (!$this->store instanceof Store || !isset($this->store->id)) {
throw new InvalidArgumentException('Store is undefined or invalid');
}
}
/**
* 平台作用域匹配 - 提供默认实现
*
2025-12-11 16:38:29 +08:00
* 从 exchange 中提取平台信息
2025-11-27 13:40:58 +08:00
* 子类可以覆盖此方法以实现自定义逻辑
*
2025-11-27 15:03:25 +08:00
* @param array $metadata
2025-11-27 13:40:58 +08:00
* @return Platform
* @throws InvalidArgumentException
*/
2025-11-27 15:03:25 +08:00
public function platformScopeMatch(array $metadata): Platform
2025-11-27 13:40:58 +08:00
{
2025-12-11 16:38:29 +08:00
return $this->extractPlatformFromExchange($this->message);
2025-11-27 13:40:58 +08:00
}
/**
* 实体匹配 - 提供默认实现
*
2025-12-11 16:38:29 +08:00
* 从 routing key 中提取实体类型
2025-11-27 13:40:58 +08:00
* 子类可以覆盖此方法以实现自定义逻辑
*
2025-11-27 15:03:25 +08:00
* @param array $metadata
2025-11-27 13:40:58 +08:00
* @return Entity
* @throws InvalidArgumentException
*/
2025-11-27 15:03:25 +08:00
public function entityMatch(array $metadata): Entity
2025-11-27 13:40:58 +08:00
{
2025-12-11 16:38:29 +08:00
return $this->extractEntityFromRoutingKey($this->message);
2025-11-27 13:40:58 +08:00
}
/**
* 唯一标识符提取 - 提供默认实现
*
2025-12-11 16:38:29 +08:00
* 子类需要覆盖此方法以实现自定义逻辑
2025-11-27 13:40:58 +08:00
*
2025-11-27 15:03:25 +08:00
* @param array $metadata
2025-12-11 16:38:29 +08:00
* @return array
2025-11-27 13:40:58 +08:00
* @throws InvalidArgumentException
*/
2025-12-11 16:38:29 +08:00
public function entityUniqueIdentifierExtract(array $metadata): array
2025-11-27 13:40:58 +08:00
{
2025-12-11 16:38:29 +08:00
// 举例说明,当 Order Entity 实体需要根据 平台 ID 和 平台订单 ID 来确定唯一性时
// 确认仓库中 Order 模型 对应的数据库字段约束条件为
// CONSTRAINT "orders_store_platform_order_unique" UNIQUE ("store_id", "platform_order_id")
// 可以从 $metadata 中分别提取 store_id 和 platform_order_id 的值
// 返回构造后的结果即可
// return ['store_id' => 123, 'platform_order_id' => 123123]
$className = static::class;
throw new InvalidArgumentException(
"Method entityUniqueIdentifierExtract() must be implemented in class '{$className}'"
);
2025-11-27 13:40:58 +08:00
}
/**
* 公司作用域匹配 - 抽象方法
*
* 必须由子类实现,因为不同平台的公司识别逻辑不同
*
2025-11-27 15:03:25 +08:00
* @param array $metadata
2025-11-27 13:40:58 +08:00
* @return Company
*/
2025-11-27 15:03:25 +08:00
abstract public function companyScopeMatch(array $metadata): Company;
2025-11-27 13:40:58 +08:00
/**
* 店铺作用域匹配 - 抽象方法
*
* 必须由子类实现,因为不同平台的店铺识别逻辑不同
*
2025-11-27 15:03:25 +08:00
* @param array $metadata
2025-11-27 13:40:58 +08:00
* @return Store
*/
2025-11-27 15:03:25 +08:00
abstract public function storeScopeMatch(array $metadata): Store;
2025-11-27 13:40:58 +08:00
/**
* 实体数据映射 - 抽象方法
*
* 必须由子类实现,因为不同平台的数据结构不同
*
2025-11-27 15:03:25 +08:00
* @param array $rawData
* @return LazyCollection
2025-11-27 13:40:58 +08:00
*/
2025-11-27 15:03:25 +08:00
abstract public function entityMap(array $rawData): LazyCollection;
2025-11-27 13:40:58 +08:00
// ==================== Getter 方法 ====================
/**
2025-11-27 15:03:25 +08:00
* 获取消息数据
2025-11-27 13:40:58 +08:00
*
2025-11-27 15:03:25 +08:00
* @return array
2025-11-27 13:40:58 +08:00
*/
2025-11-27 15:03:25 +08:00
public function getData(): array
2025-11-27 13:40:58 +08:00
{
2025-11-27 15:03:25 +08:00
return $this->data;
2025-11-27 13:40:58 +08:00
}
2025-12-11 16:38:29 +08:00
/**
* 获取消息对象
*
* @return ConsumerMessageInterface
*/
public function getMessage(): ConsumerMessageInterface
{
return $this->message;
}
2025-11-27 13:40:58 +08:00
/**
* 获取平台对象
*
* @return Platform
*/
public function getPlatform(): Platform
{
return $this->platform;
}
/**
* 获取公司对象
*
* @return Company
*/
public function getCompany(): Company
{
return $this->company;
}
/**
* 获取店铺对象
*
* @return Store
*/
public function getStore(): Store
{
return $this->store;
}
}