Closed NHZEX closed 1 month ago
实际用例
/**
* 产品模型.
*
* @property int $id
* @property int $status
* @property string $name
* @property int $createdAt
* @property int $createdBy
* @property int $updatedAt
* @property int $updatedBy
* @property int $lockVersion
* @property PrintParameters $printParams
*/
final class ProductModel extends ModelBaseV2
{
protected $table = 'product';
protected $pk = 'id';
protected $convertNameToCamel = true;
protected $type = [
'print_params' => PrintParameters::class,
];
}
/**
* DTO 类
*/
class PrintParameters extends DTOBase implements FieldTypeTransform
{
public function __construct(
public readonly int $printXxxId,
public readonly int $printAbcId,
public readonly Vector2d $printShift,
) {
}
public static function modelReadValue($value, $model): ?static
{
if (empty($value)) {
return null;
}
$result = json_decode($value, true);
if (empty($result)) {
return null;
}
return static::fromData($result);
}
public static function modelWriteValue($value, $model): ?string
{
if (empty($value)) {
return null;
}
return json_encode_ex($value);
}
}
abstract class DTOBase implements JsonSerializable
{
public function toArray(): array
{
return get_object_vars($this);
}
public function jsonSerialize(): array
{
return $this->toArray();
}
/**
* @throws JsonException
*/
public function __toString(): string
{
return json_encode($this, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE | \JSON_THROW_ON_ERROR);
}
public static function fromData(array|string $arrOrJson): static
{
$source = \is_string($arrOrJson)
? Source::json($arrOrJson)
: Source::array($arrOrJson);
$cache = thinkApp::getInstance()->cache;
$cache = new FileWatchingCache($cache);
$builder = (new MapperBuilder())
->withCache($cache)
->supportDateFormats(\DATE_ATOM)
->allowPermissiveTypes()
->allowSuperfluousKeys()
->enableFlexibleCasting();
return $builder->mapper()->map(static::class, $source);
}
}
/**
* 声明接口
*/
interface FieldTypeTransform
{
/**
* @param Model $model
*/
public static function modelReadValue($value, $model);
/**
* @param Model $model
*/
public static function modelWriteValue($value, $model);
}
重提这个请求:https://github.com/top-think/think-orm/pull/210
解决的痛点:
__construct
作为入口,那能使实例构建更加灵活。DTO
类,一般都实现了fromXXX
,toXXX
静态方法作为入口,当前__construct
和__toString
的接入组合灵活性太差了。Model
作为上下文参数,这个能实现更加底层的需求,比如更加字典状态在实例化DTO
时处理一些历史遗留问题。当然这个是有风险了,只推荐访问getData
,getOrigin
这种无副作用的访问方式,不然容易造成死循环的情况。提到的优秀反序列化工具库,基本都是提供类名重新实例化的。