Skip to content

Commit

Permalink
实体模型增加只读和废弃字段支持 非严格模式下支持定义type
Browse files Browse the repository at this point in the history
  • Loading branch information
liu21st committed Nov 20, 2024
1 parent 7fac0a5 commit 642e7bf
Showing 1 changed file with 47 additions and 23 deletions.
70 changes: 47 additions & 23 deletions src/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ public function __construct(array | object $data = [], ?Model $model = null)
'together' => [],
'allow' => [],
'strict_mode' => true,
'type' => $options['type'] ?? [],
'readonly' => $options['readonly'] ?? [],
'disuse' => $options['disuse'] ?? [],
'hidden' => $options['hidden'] ?? [],
'visible' => $options['visible'] ?? [],
'append' => $options['append'] ?? [],
Expand Down Expand Up @@ -127,39 +130,39 @@ protected function initializeData(array | object $data, bool $fromSave = false)

// 实体模型赋值
foreach ($data as $name => $val) {
if (in_array($name, self::$weakMap[$this]['disuse'])) {
// 废弃字段
continue;
}

if (!empty(self::$weakMap[$this]['mapping'])) {
// 字段映射
$key = array_search($name, self::$weakMap[$this]['mapping']);
if (is_string($key)) {
$name = $key;
}
}

$trueName = $this->getRealFieldName($name);
if ($this->model()->getPk() == $trueName) {
// 记录主键值
$this->model()->setKey($val);
$this->model()->exists(true);
}

if (in_array($trueName, $fields)) {
// 读取数据后进行类型转换
$value = $this->readTransform($val, $schema[$trueName] ?? 'string');

$this->$trueName = $value;
// 数据赋值
$this->$trueName = $value;
// 记录原始数据
$origin[$trueName] = $value;
}
}

if (!empty($origin)) {
if ($this->model()->getKey()) {
$this->model()->exists(true);
}

if (!$fromSave) {
$this->setWeakData('origin', $origin);
}

if (!$this->isStrictMode()) {
// 非严格定义模式下 采用动态属性
$this->setWeakData('data', $origin);
}
if (!empty($origin) && !$fromSave) {
$this->setWeakData('origin', $origin);
}
}

Expand Down Expand Up @@ -319,7 +322,7 @@ protected function getFields(?string $field = null)
$this->setWeakData('strict_mode', false);
// 获取数据表信息
$fields = $this->model()->getFieldsType($this->model()->getTable());
$array = array_merge($fields, $this->model()->getType());
$array = array_merge($fields, self::$weakMap[$this]['type'] ?: $this->model()->getType());
foreach ($array as $name => $type) {
$name = $this->getRealFieldName($name);
$schema[$name] = $type;
Expand Down Expand Up @@ -516,30 +519,38 @@ public function save(array | object $data = []): bool

$data = $this->getData();
$origin = $this->getOrigin();
$allow = $this->getWeakData('allow');
$allow = $this->getWeakData('allow') ?: array_keys($this->getFields());
$readonly = $this->getWeakData('readonly');
$disuse = $this->getWeakData('disuse');
$allow = array_diff($allow, $readonly, $disuse);
$isUpdate = $this->model()->getKey() && !$this->model()->isForce();

foreach ($data as $name => &$val) {
if ($val instanceof Entity) {
$relations[$name] = $val;
unset($data[$name]);
} elseif ($val instanceof Collection) {
unset($data[$name]);
} elseif (!empty($allow) && !in_array($name, $allow)) {
} elseif ($val instanceof Collection || !in_array($name, $allow)) {
// 禁止更新字段(包括只读、废弃和数据集)
unset($data[$name]);
} elseif ($isUpdate && ((isset($origin[$name]) && $val === $origin[$name]) || $this->model()->getPk() == $name)) {
} elseif ($isUpdate && $this->isNotRequireUpdate($name, $val, $origin)) {
// 无需更新字段
unset($data[$name]);
} else {
// 类型转换
$val = $this->writeTransform($val, $this->getFields($name));
// 统一执行修改器或类型转换后写入
$method = 'set' . Str::studly($name) . 'Attr';
// 修改器
if (method_exists($this, $method)) {
$val = $this->$method($val, $data);
} else {
// 类型转换
$val = $this->writeTransform($val, $this->getFields($name));
}
}
}

if (empty($data)) {
return false;
}

if (!self::$weakMap[$this]['strict']) {
// 非严格模式下 自动转换为小写下划线规范
foreach ($data as $name => $val) {
Expand All @@ -566,6 +577,19 @@ public function save(array | object $data = []): bool
return true;
}

/**
* 检查字段是否有更新(主键无需更新).
*
* @param string $name 字段
* @param mixed $val 值
* @param array $origin 原始数据
* @return bool
*/
protected function isNotRequireUpdate(string $name, $val, array $origin): bool
{
return (array_key_exists($name, $origin) && $val === $origin[$name]) || $this->model()->getPk() == $name;
}

/**
* 写入模型关联数据(一对一).
*
Expand Down

0 comments on commit 642e7bf

Please sign in to comment.