阅读(3630) (11)

Laravel 8 值对象类型转换

2021-07-08 09:45:01 更新

你不仅可以将数据转换成原生的数据类型,还可以将数据转换成对象。两种自定义类型转换的定义方式非常类似。但是将数据转换成对象的自定义转换类中的 set 方法需要返回键值对数组,用于设置原始、可存储的值到对应的模型中。

举个例子,定义一个自定义类型转换类用于将多个模型属性值转换成单个 Address 值对象,假设 Address 对象有两个公有属性 lineOnelineTwo

<?php

namespace App\Casts;

use App\Models\Address;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use InvalidArgumentException;

class Address implements CastsAttributes
{
    /**
     * 将取出的数据进行转换
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return \App\Models\Address
     */
    public function get($model, $key, $value, $attributes)
    {
        return new Address(
            $attributes['address_line_one'],
            $attributes['address_line_two']
        );
    }

    /**
     * 转换成将要进行存储的值
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  \App\Models\Address  $value
     * @param  array  $attributes
     * @return array
     */
    public function set($model, $key, $value, $attributes)
    {
        if (! $value instanceof Address) {
            throw new InvalidArgumentException('The given value is not an Address instance.');
        }

        return [
            'address_line_one' => $value->lineOne,
            'address_line_two' => $value->lineTwo,
        ];
    }
} 

进行值对象类型转换后,任何对值对象的数据转换将会自动同步回模型中:

$user = App\Models\User::find(1);

$user->address->lineOne = 'Updated Address Value';

$user->save(); 

技巧:如果想将包含值对象的 Eloquent 模型序列化为 JSON 或数组,你只需让该模型实现 Illuminate\Contracts\Support\ArrayableJsonSerializable 接口即可。