6 changed files with 1141 additions and 41 deletions
@ -0,0 +1,823 @@ |
|||||
|
<?php |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Niucloud-admin 企业快速开发的多应用管理平台 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | 官方网址:https://www.niucloud.com |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | niucloud团队 版权所有 开源版本可自由商用 |
||||
|
// +---------------------------------------------------------------------- |
||||
|
// | Author: Niucloud Team |
||||
|
// +---------------------------------------------------------------------- |
||||
|
|
||||
|
namespace app\service\core\sys; |
||||
|
|
||||
|
use core\base\BaseCoreService; |
||||
|
use think\facade\Cache; |
||||
|
use think\facade\Db; |
||||
|
use think\Model; |
||||
|
use Exception; |
||||
|
|
||||
|
/** |
||||
|
* 字段值包装类,支持链式调用 |
||||
|
* Class FieldValue |
||||
|
*/ |
||||
|
class FieldValue |
||||
|
{ |
||||
|
/** |
||||
|
* 原始值 |
||||
|
* @var mixed |
||||
|
*/ |
||||
|
protected $value; |
||||
|
|
||||
|
/** |
||||
|
* 字段映射服务实例 |
||||
|
* @var CoreFieldMappingService |
||||
|
*/ |
||||
|
protected $service; |
||||
|
|
||||
|
/** |
||||
|
* 字段名 |
||||
|
* @var string |
||||
|
*/ |
||||
|
protected $field_name; |
||||
|
|
||||
|
/** |
||||
|
* 构造函数 |
||||
|
* @param mixed $value 原始值 |
||||
|
* @param CoreFieldMappingService $service 服务实例 |
||||
|
* @param string $field_name 字段名 |
||||
|
*/ |
||||
|
public function __construct($value, CoreFieldMappingService $service, string $field_name) |
||||
|
{ |
||||
|
$this->value = $value; |
||||
|
$this->service = $service; |
||||
|
$this->field_name = $field_name; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取原始值 |
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function getValue() |
||||
|
{ |
||||
|
return $this->value; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 链式调用关系查询 |
||||
|
* @param string $relation_table 关系表名 |
||||
|
* @param string $display_field 显示字段 |
||||
|
* @param string $key_field 关键字段,默认为id |
||||
|
* @param array $conditions 额外查询条件 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function withRelation(string $relation_table, string $display_field, string $key_field = 'id', array $conditions = [], bool $use_cache = true) |
||||
|
{ |
||||
|
if ($this->value === null) { |
||||
|
return $this->value; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
// 生成缓存键 |
||||
|
$cache_key = "relation_chain_{$this->field_name}_" . md5(serialize([ |
||||
|
'value' => $this->value, |
||||
|
'table' => $relation_table, |
||||
|
'display_field' => $display_field, |
||||
|
'key_field' => $key_field, |
||||
|
'conditions' => $conditions |
||||
|
])); |
||||
|
|
||||
|
if ($use_cache) { |
||||
|
$cached_value = Cache::get($cache_key); |
||||
|
if ($cached_value !== false && $cached_value !== null) { |
||||
|
return $cached_value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 构建查询 |
||||
|
$query = Db::table($relation_table) |
||||
|
->where($key_field, $this->value) |
||||
|
->field($display_field); |
||||
|
|
||||
|
// 添加额外条件 |
||||
|
if (!empty($conditions)) { |
||||
|
$query->where($conditions); |
||||
|
} |
||||
|
|
||||
|
$result = $query->find(); |
||||
|
$converted_value = $result ? $result[$display_field] : $this->value; |
||||
|
|
||||
|
// 缓存结果 |
||||
|
if ($use_cache) { |
||||
|
Cache::tag(CoreFieldMappingService::$cache_tag_name)->set($cache_key, $converted_value, 3600); |
||||
|
} |
||||
|
|
||||
|
return $converted_value; |
||||
|
|
||||
|
} catch (Exception $e) { |
||||
|
trace($e->getMessage(), 'error'); |
||||
|
return $this->value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 转换为字符串时返回原始值 |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function __toString() |
||||
|
{ |
||||
|
return (string)$this->value; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 支持直接访问值的魔术方法 |
||||
|
* @param string $name |
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function __get(string $name) |
||||
|
{ |
||||
|
if ($name === 'value') { |
||||
|
return $this->value; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 数据库字段映射服务层 |
||||
|
* |
||||
|
* 支持字段映射、枚举值自动转义、关系查询链式调用等功能 |
||||
|
* |
||||
|
* 使用示例: |
||||
|
* |
||||
|
* 1. 基本用法: |
||||
|
* ```php |
||||
|
* $mapping = new CoreFieldMappingService('users', ['id' => 1]); |
||||
|
* $name = $mapping->getValue('name'); // 获取用户名 |
||||
|
* ``` |
||||
|
* |
||||
|
* 2. 枚举值自动转义: |
||||
|
* ```php |
||||
|
* $mapping = new CoreFieldMappingService('users', ['id' => 1]); |
||||
|
* $mapping->setFieldEnum('status', [1 => '启用', 0 => '禁用']); |
||||
|
* $status = $mapping->getValue('status'); // 直接返回 '启用' 或 '禁用' |
||||
|
* ``` |
||||
|
* |
||||
|
* 3. 关系查询链式调用: |
||||
|
* ```php |
||||
|
* $mapping = new CoreFieldMappingService('orders', ['id' => 1]); |
||||
|
* $username = $mapping->getValueWithChain('user_id') |
||||
|
* ->withRelation('users', 'username'); // 获取用户名 |
||||
|
* ``` |
||||
|
* |
||||
|
* 4. 批量设置枚举和关系: |
||||
|
* ```php |
||||
|
* $mapping = new CoreFieldMappingService('orders'); |
||||
|
* $mapping->setFieldEnums([ |
||||
|
* 'status' => [1 => '已付款', 2 => '已发货', 3 => '已完成'], |
||||
|
* 'type' => [1 => '普通订单', 2 => '预售订单'] |
||||
|
* ]); |
||||
|
* $mapping->setFieldRelation('user_id', 'users', 'username'); |
||||
|
* ``` |
||||
|
* |
||||
|
* Class CoreFieldMappingService |
||||
|
* @package app\service\core\sys |
||||
|
*/ |
||||
|
class CoreFieldMappingService extends BaseCoreService |
||||
|
{ |
||||
|
/** |
||||
|
* 缓存标签名 |
||||
|
* @var string |
||||
|
*/ |
||||
|
public static $cache_tag_name = 'field_mapping'; |
||||
|
|
||||
|
/** |
||||
|
* 表名 |
||||
|
* @var string |
||||
|
*/ |
||||
|
protected $table_name; |
||||
|
|
||||
|
/** |
||||
|
* 查询条件 |
||||
|
* @var array |
||||
|
*/ |
||||
|
protected $conditions; |
||||
|
|
||||
|
/** |
||||
|
* 字段映射配置 |
||||
|
* @var array |
||||
|
*/ |
||||
|
protected $field_mapping; |
||||
|
|
||||
|
/** |
||||
|
* 枚举映射配置 |
||||
|
* @var array |
||||
|
*/ |
||||
|
protected $enum_mapping; |
||||
|
|
||||
|
/** |
||||
|
* 关系映射配置 |
||||
|
* @var array |
||||
|
*/ |
||||
|
protected $relation_mapping; |
||||
|
|
||||
|
/** |
||||
|
* 构造函数 |
||||
|
* @param string $table_name 表名 |
||||
|
* @param array $conditions 查询条件 |
||||
|
* @param array $field_mapping 字段映射配置 |
||||
|
* @param array $enum_mapping 枚举映射配置 |
||||
|
* @param array $relation_mapping 关系映射配置 |
||||
|
*/ |
||||
|
public function __construct(string $table_name, array $conditions = [], array $field_mapping = [], array $enum_mapping = [], array $relation_mapping = []) |
||||
|
{ |
||||
|
parent::__construct(); |
||||
|
$this->table_name = $table_name; |
||||
|
$this->conditions = $conditions; |
||||
|
$this->field_mapping = $field_mapping; |
||||
|
$this->enum_mapping = $enum_mapping; |
||||
|
$this->relation_mapping = $relation_mapping; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取字段映射关系 |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getFieldMapping(): array |
||||
|
{ |
||||
|
return $this->field_mapping; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 设置字段映射关系 |
||||
|
* @param array $field_mapping |
||||
|
* @return $this |
||||
|
*/ |
||||
|
public function setFieldMapping(array $field_mapping): self |
||||
|
{ |
||||
|
$this->field_mapping = $field_mapping; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 设置查询条件 |
||||
|
* @param array $conditions |
||||
|
* @return $this |
||||
|
*/ |
||||
|
public function setConditions(array $conditions): self |
||||
|
{ |
||||
|
$this->conditions = $conditions; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取查询条件 |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getConditions(): array |
||||
|
{ |
||||
|
return $this->conditions; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 从查询结果中获取指定字段的值 |
||||
|
* @param string $field_name 字段名 |
||||
|
* @param mixed $default_value 默认值 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @param bool $auto_convert_enum 是否自动转义枚举值,默认true |
||||
|
* @param bool $return_wrapper 是否返回FieldValue包装对象以支持链式调用,默认false |
||||
|
* @return mixed|FieldValue |
||||
|
*/ |
||||
|
public function getValue(string $field_name, $default_value = null, bool $use_cache = true, bool $auto_convert_enum = true, bool $return_wrapper = false) |
||||
|
{ |
||||
|
try { |
||||
|
// 生成缓存键 |
||||
|
$cache_key = $this->generateCacheKey($field_name); |
||||
|
|
||||
|
if ($use_cache) { |
||||
|
// 尝试从缓存获取 |
||||
|
$cached_value = Cache::get($cache_key); |
||||
|
if ($cached_value !== false && $cached_value !== null) { |
||||
|
return $cached_value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 检查字段映射 |
||||
|
$actual_field = $this->getActualFieldName($field_name); |
||||
|
|
||||
|
// 构建查询 |
||||
|
$query = Db::table($this->table_name); |
||||
|
|
||||
|
// 添加查询条件 |
||||
|
if (!empty($this->conditions)) { |
||||
|
$query->where($this->conditions); |
||||
|
} |
||||
|
|
||||
|
// 执行查询 |
||||
|
$result = $query->field($actual_field)->find(); |
||||
|
|
||||
|
if (empty($result)) { |
||||
|
return $default_value; |
||||
|
} |
||||
|
|
||||
|
$value = $result[$actual_field] ?? $default_value; |
||||
|
|
||||
|
// 自动转义枚举值 |
||||
|
if ($auto_convert_enum && $value !== null && $value !== $default_value && isset($this->enum_mapping[$field_name])) { |
||||
|
$enum_config = $this->enum_mapping[$field_name]; |
||||
|
$value = $enum_config[$value] ?? $value; |
||||
|
} |
||||
|
|
||||
|
// 缓存结果 |
||||
|
if ($use_cache && $value !== null) { |
||||
|
Cache::tag(self::$cache_tag_name)->set($cache_key, $value, 3600); // 缓存1小时 |
||||
|
} |
||||
|
|
||||
|
// 返回包装对象或原始值 |
||||
|
if ($return_wrapper) { |
||||
|
return new FieldValue($value, $this, $field_name); |
||||
|
} |
||||
|
|
||||
|
return $value; |
||||
|
|
||||
|
} catch (Exception $e) { |
||||
|
// 记录错误日志 |
||||
|
trace($e->getMessage(), 'error'); |
||||
|
return $default_value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取字段值并返回支持链式调用的包装对象 |
||||
|
* @param string $field_name 字段名 |
||||
|
* @param mixed $default_value 默认值 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @param bool $auto_convert_enum 是否自动转义枚举值,默认true |
||||
|
* @return FieldValue |
||||
|
*/ |
||||
|
public function getValueWithChain(string $field_name, $default_value = null, bool $use_cache = true, bool $auto_convert_enum = true): FieldValue |
||||
|
{ |
||||
|
return $this->getValue($field_name, $default_value, $use_cache, $auto_convert_enum, true); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 批量获取多个字段的值 |
||||
|
* @param array $field_names 字段名数组 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getValues(array $field_names, bool $use_cache = true): array |
||||
|
{ |
||||
|
try { |
||||
|
$result = []; |
||||
|
|
||||
|
// 生成缓存键 |
||||
|
$cache_key = $this->generateCacheKey(implode(',', $field_names)); |
||||
|
|
||||
|
if ($use_cache) { |
||||
|
// 尝试从缓存获取 |
||||
|
$cached_result = Cache::get($cache_key); |
||||
|
if ($cached_result !== false && $cached_result !== null) { |
||||
|
return $cached_result; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 获取实际字段名 |
||||
|
$actual_fields = []; |
||||
|
foreach ($field_names as $field_name) { |
||||
|
$actual_fields[] = $this->getActualFieldName($field_name); |
||||
|
} |
||||
|
|
||||
|
// 构建查询 |
||||
|
$query = Db::table($this->table_name); |
||||
|
|
||||
|
// 添加查询条件 |
||||
|
if (!empty($this->conditions)) { |
||||
|
$query->where($this->conditions); |
||||
|
} |
||||
|
|
||||
|
// 执行查询 |
||||
|
$data = $query->field(implode(',', $actual_fields))->find(); |
||||
|
|
||||
|
if (!empty($data)) { |
||||
|
// 映射回原始字段名 |
||||
|
foreach ($field_names as $index => $field_name) { |
||||
|
$actual_field = $actual_fields[$index]; |
||||
|
$result[$field_name] = $data[$actual_field] ?? null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 缓存结果 |
||||
|
if ($use_cache && !empty($result)) { |
||||
|
Cache::tag(self::$cache_tag_name)->set($cache_key, $result, 3600); // 缓存1小时 |
||||
|
} |
||||
|
|
||||
|
return $result; |
||||
|
|
||||
|
} catch (Exception $e) { |
||||
|
// 记录错误日志 |
||||
|
trace($e->getMessage(), 'error'); |
||||
|
return []; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取实际字段名(考虑字段映射) |
||||
|
* @param string $field_name |
||||
|
* @return string |
||||
|
*/ |
||||
|
protected function getActualFieldName(string $field_name): string |
||||
|
{ |
||||
|
return $this->field_mapping[$field_name] ?? $field_name; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成缓存键 |
||||
|
* @param string $field_name |
||||
|
* @return string |
||||
|
*/ |
||||
|
protected function generateCacheKey(string $field_name): string |
||||
|
{ |
||||
|
$conditions_hash = md5(serialize($this->conditions)); |
||||
|
return "field_mapping_{$this->table_name}_{$field_name}_{$conditions_hash}"; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 清除缓存 |
||||
|
* @param string|null $field_name 指定字段名,为空则清除所有相关缓存 |
||||
|
* @return bool |
||||
|
*/ |
||||
|
public function clearCache(string $field_name = null): bool |
||||
|
{ |
||||
|
if ($field_name) { |
||||
|
$cache_key = $this->generateCacheKey($field_name); |
||||
|
return Cache::delete($cache_key); |
||||
|
} else { |
||||
|
return Cache::tag(self::$cache_tag_name)->clear(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 检查表是否存在 |
||||
|
* @return bool |
||||
|
*/ |
||||
|
public function tableExists(): bool |
||||
|
{ |
||||
|
try { |
||||
|
$tables = Db::query("SHOW TABLES LIKE '{$this->table_name}'"); |
||||
|
return !empty($tables); |
||||
|
} catch (Exception $e) { |
||||
|
trace($e->getMessage(), 'error'); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取表的字段信息 |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getTableFields(): array |
||||
|
{ |
||||
|
try { |
||||
|
$cache_key = "table_fields_{$this->table_name}"; |
||||
|
|
||||
|
// 尝试从缓存获取 |
||||
|
$cached_fields = Cache::get($cache_key); |
||||
|
if ($cached_fields !== false && $cached_fields !== null) { |
||||
|
return $cached_fields; |
||||
|
} |
||||
|
|
||||
|
$fields = Db::query("DESCRIBE {$this->table_name}"); |
||||
|
|
||||
|
// 缓存字段信息 |
||||
|
Cache::tag(self::$cache_tag_name)->set($cache_key, $fields, 7200); // 缓存2小时 |
||||
|
|
||||
|
return $fields; |
||||
|
|
||||
|
} catch (Exception $e) { |
||||
|
trace($e->getMessage(), 'error'); |
||||
|
return []; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 验证字段是否存在 |
||||
|
* @param string $field_name |
||||
|
* @return bool |
||||
|
*/ |
||||
|
public function fieldExists(string $field_name): bool |
||||
|
{ |
||||
|
$fields = $this->getTableFields(); |
||||
|
$actual_field = $this->getActualFieldName($field_name); |
||||
|
|
||||
|
foreach ($fields as $field) { |
||||
|
if ($field['Field'] === $actual_field) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 设置枚举映射配置 |
||||
|
* @param array $enum_mapping |
||||
|
* @return $this |
||||
|
*/ |
||||
|
public function setEnumMapping(array $enum_mapping): self |
||||
|
{ |
||||
|
$this->enum_mapping = $enum_mapping; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 为单个字段设置枚举映射 |
||||
|
* @param string $field_name 字段名 |
||||
|
* @param array $enum_values 枚举值映射 |
||||
|
* @return $this |
||||
|
*/ |
||||
|
public function setFieldEnum(string $field_name, array $enum_values): self |
||||
|
{ |
||||
|
$this->enum_mapping[$field_name] = $enum_values; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 批量设置多个字段的枚举映射 |
||||
|
* @param array $field_enums 字段枚举映射数组,格式:['field_name' => ['value' => 'label']] |
||||
|
* @return $this |
||||
|
*/ |
||||
|
public function setFieldEnums(array $field_enums): self |
||||
|
{ |
||||
|
foreach ($field_enums as $field_name => $enum_values) { |
||||
|
$this->enum_mapping[$field_name] = $enum_values; |
||||
|
} |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取枚举映射配置 |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getEnumMapping(): array |
||||
|
{ |
||||
|
return $this->enum_mapping; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 设置关系映射配置 |
||||
|
* @param array $relation_mapping |
||||
|
* @return $this |
||||
|
*/ |
||||
|
public function setRelationMapping(array $relation_mapping): self |
||||
|
{ |
||||
|
$this->relation_mapping = $relation_mapping; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 为单个字段设置关系映射 |
||||
|
* @param string $field_name 字段名 |
||||
|
* @param string $relation_table 关系表名 |
||||
|
* @param string $display_field 显示字段 |
||||
|
* @param string $key_field 关键字段,默认为id |
||||
|
* @param array $conditions 额外查询条件 |
||||
|
* @return $this |
||||
|
*/ |
||||
|
public function setFieldRelation(string $field_name, string $relation_table, string $display_field, string $key_field = 'id', array $conditions = []): self |
||||
|
{ |
||||
|
$this->relation_mapping[$field_name] = [ |
||||
|
'table' => $relation_table, |
||||
|
'display_field' => $display_field, |
||||
|
'key_field' => $key_field, |
||||
|
'conditions' => $conditions |
||||
|
]; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 批量设置多个字段的关系映射 |
||||
|
* @param array $field_relations 字段关系映射数组 |
||||
|
* @return $this |
||||
|
*/ |
||||
|
public function setFieldRelations(array $field_relations): self |
||||
|
{ |
||||
|
foreach ($field_relations as $field_name => $relation_config) { |
||||
|
if (is_array($relation_config) && isset($relation_config['table']) && isset($relation_config['display_field'])) { |
||||
|
$this->relation_mapping[$field_name] = $relation_config; |
||||
|
} |
||||
|
} |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取关系映射配置 |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getRelationMapping(): array |
||||
|
{ |
||||
|
return $this->relation_mapping; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 转换枚举值 |
||||
|
* @param string $field_name 字段名 |
||||
|
* @param mixed $value 原始值 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function convertEnumValue(string $field_name, $value, bool $use_cache = true) |
||||
|
{ |
||||
|
try { |
||||
|
// 检查是否配置了枚举映射 |
||||
|
if (!isset($this->enum_mapping[$field_name])) { |
||||
|
return $value; |
||||
|
} |
||||
|
|
||||
|
$enum_config = $this->enum_mapping[$field_name]; |
||||
|
|
||||
|
// 生成缓存键 |
||||
|
$cache_key = "enum_convert_{$field_name}_" . md5(serialize($value)); |
||||
|
|
||||
|
if ($use_cache) { |
||||
|
$cached_value = Cache::get($cache_key); |
||||
|
if ($cached_value !== false && $cached_value !== null) { |
||||
|
return $cached_value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 执行枚举转换 |
||||
|
$converted_value = $enum_config[$value] ?? $value; |
||||
|
|
||||
|
// 缓存结果 |
||||
|
if ($use_cache) { |
||||
|
Cache::tag(self::$cache_tag_name)->set($cache_key, $converted_value, 3600); |
||||
|
} |
||||
|
|
||||
|
return $converted_value; |
||||
|
|
||||
|
} catch (Exception $e) { |
||||
|
trace($e->getMessage(), 'error'); |
||||
|
return $value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 转换关系ID值 |
||||
|
* @param string $field_name 字段名 |
||||
|
* @param mixed $value 关系ID值 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function convertRelationValue(string $field_name, $value, bool $use_cache = true) |
||||
|
{ |
||||
|
try { |
||||
|
// 检查是否配置了关系映射 |
||||
|
if (!isset($this->relation_mapping[$field_name])) { |
||||
|
return $value; |
||||
|
} |
||||
|
|
||||
|
$relation_config = $this->relation_mapping[$field_name]; |
||||
|
|
||||
|
// 验证关系配置 |
||||
|
if (!isset($relation_config['table']) || !isset($relation_config['display_field'])) { |
||||
|
return $value; |
||||
|
} |
||||
|
|
||||
|
// 生成缓存键 |
||||
|
$cache_key = "relation_convert_{$field_name}_" . md5(serialize($value)); |
||||
|
|
||||
|
if ($use_cache) { |
||||
|
$cached_value = Cache::get($cache_key); |
||||
|
if ($cached_value !== false && $cached_value !== null) { |
||||
|
return $cached_value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 构建查询 |
||||
|
$relation_table = $relation_config['table']; |
||||
|
$display_field = $relation_config['display_field']; |
||||
|
$key_field = $relation_config['key_field'] ?? 'id'; |
||||
|
|
||||
|
$query = Db::table($relation_table) |
||||
|
->where($key_field, $value) |
||||
|
->field($display_field); |
||||
|
|
||||
|
// 添加额外条件 |
||||
|
if (isset($relation_config['conditions']) && is_array($relation_config['conditions'])) { |
||||
|
$query->where($relation_config['conditions']); |
||||
|
} |
||||
|
|
||||
|
$result = $query->find(); |
||||
|
$converted_value = $result ? $result[$display_field] : $value; |
||||
|
|
||||
|
// 缓存结果 |
||||
|
if ($use_cache) { |
||||
|
Cache::tag(self::$cache_tag_name)->set($cache_key, $converted_value, 3600); |
||||
|
} |
||||
|
|
||||
|
return $converted_value; |
||||
|
|
||||
|
} catch (Exception $e) { |
||||
|
trace($e->getMessage(), 'error'); |
||||
|
return $value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 批量转换字段值 |
||||
|
* @param array $data 原始数据 |
||||
|
* @param array $convert_fields 需要转换的字段列表 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function convertValues(array $data, array $convert_fields = [], bool $use_cache = true): array |
||||
|
{ |
||||
|
try { |
||||
|
if (empty($data)) { |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
$converted_data = $data; |
||||
|
|
||||
|
// 如果未指定转换字段,则根据配置自动确定 |
||||
|
if (empty($convert_fields)) { |
||||
|
$convert_fields = array_merge( |
||||
|
array_keys($this->enum_mapping), |
||||
|
array_keys($this->relation_mapping) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
foreach ($convert_fields as $field_name) { |
||||
|
if (!isset($data[$field_name])) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
$original_value = $data[$field_name]; |
||||
|
|
||||
|
// 枚举转换 |
||||
|
if (isset($this->enum_mapping[$field_name])) { |
||||
|
$converted_data[$field_name] = $this->convertEnumValue($field_name, $original_value, $use_cache); |
||||
|
} |
||||
|
// 关系转换 |
||||
|
elseif (isset($this->relation_mapping[$field_name])) { |
||||
|
$converted_data[$field_name] = $this->convertRelationValue($field_name, $original_value, $use_cache); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return $converted_data; |
||||
|
|
||||
|
} catch (Exception $e) { |
||||
|
trace($e->getMessage(), 'error'); |
||||
|
return $data; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取带转义的字段值 |
||||
|
* @param string $field_name 字段名 |
||||
|
* @param mixed $default_value 默认值 |
||||
|
* @param bool $convert 是否进行转义 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function getConvertedValue(string $field_name, $default_value = null, bool $convert = true, bool $use_cache = true) |
||||
|
{ |
||||
|
$value = $this->getValue($field_name, $default_value, $use_cache); |
||||
|
|
||||
|
if (!$convert || $value === null || $value === $default_value) { |
||||
|
return $value; |
||||
|
} |
||||
|
|
||||
|
// 枚举转换 |
||||
|
if (isset($this->enum_mapping[$field_name])) { |
||||
|
return $this->convertEnumValue($field_name, $value, $use_cache); |
||||
|
} |
||||
|
|
||||
|
// 关系转换 |
||||
|
if (isset($this->relation_mapping[$field_name])) { |
||||
|
return $this->convertRelationValue($field_name, $value, $use_cache); |
||||
|
} |
||||
|
|
||||
|
return $value; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 批量获取带转义的字段值 |
||||
|
* @param array $field_names 字段名数组 |
||||
|
* @param bool $convert 是否进行转义 |
||||
|
* @param bool $use_cache 是否使用缓存 |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getConvertedValues(array $field_names, bool $convert = true, bool $use_cache = true): array |
||||
|
{ |
||||
|
$values = $this->getValues($field_names, $use_cache); |
||||
|
|
||||
|
if (!$convert || empty($values)) { |
||||
|
return $values; |
||||
|
} |
||||
|
|
||||
|
return $this->convertValues($values, $field_names, $use_cache); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue