Laravel Model的$casts使用

$castsModel提供的一个类型转换的数组,在使用该属性时,无论是设置数据还是获取数据,都将会把指定字段转换为指定的类型,但只在特定方式下有效:

示例类

class Test extends Model 
{
    protected $casts = [
        'data' => 'json'
    ]
}

有效的例子

获取数据时

获取数据时,转换规则如下:

# fromJson实际执行的是json_decode
protected function castAttribute($key, $value)
{
    if (is_null($value)) {
        return $value;
    }
    switch ($this->getCastType($key)) {
        case 'int':
        case 'integer':
            return (int) $value;
        case 'real':
        case 'float':
        case 'double':
            return (float) $value;
        case 'string':
            return (string) $value;
        case 'bool':
        case 'boolean':
            return (bool) $value;
        case 'object':
            return $this->fromJson($value, true);
        case 'array':
        case 'json':
            return $this->fromJson($value);
        case 'collection':
            return new BaseCollection($this->fromJson($value));
        case 'date':
            return $this->asDate($value);
        case 'datetime':
            return $this->asDateTime($value);
        case 'timestamp':
            return $this->asTimestamp($value);
        default:
            return $value;
    }
}
下面的例子都会应用$casts的类型转换规则

1.使用了toArray函数

$model = app(Test::class)->find(1)->toArray();

2.使用了toJson函数

# 使用toJson时,他将先调用toArray,再调用json_encode
$model = app(Test::class)->find(1)->toJson();
设置属性时

设置属性时,只对目标类型为时间类型'date', 'datetime'对象类型'array', 'json', 'object', 'collection'做转换,对其他类型不做处理。时间类型将根据dateFormat设置的格式做处理,对象类型将转换为json。类型转换是在setAttribute函数中进行的,所以只要调用了setAttribute函数,都会应用$casts属性做类型转换。但是如果使用了修改器,如:setDataAttribute$casts将无效。

以下方式将都会应用$casts属性

1.使用Modelfill()函数填充属性时

$data = ['data' => ['test' => '这是数据']];
$model = app(Test::class)->fill($data)->save();

2.使用的Modelupdate()函数时

$data = ['data' => ['test' => '这是数据']];
$model = app(Test::class)->update($data);

3.直接给model赋值,这种方式会通过__set去调用setAttribute函数

$data = ['test' => '这是数据'];
$model = app(Test::class)->find(1);
$model->data = $data;
$model->save();

4.使用setAttribute函数时

$data = ['test' => '这是数据'];
$model = app(Test::class)->find(1);
$model->setAttribute('data', $data);
$model->save();

无效的例子

它们将无法应用$casts属性做类型转换,因为他们都没有经过ModelsetAttribute函数。

1.使用query直接操作数据将报错

$data = ['test' => '这是数据'];
$model = app(Test::class);
$model->newQuery()->where('id', 1)->update($data)

2.使用了修改器

# 定义修改器,将不会应用$casts属性做类型转换
public function setDataAttribute(array $data)
{
    return json_encode($data);
}

# 虽然经过了setAttribute函数,但是修改器的优先级比$casts高
$data = ['test' => '这是数据'];
$model = app(Test::class)->fill($data)->save();

以下是setAttribute函数

    /**
     * Set a given attribute on the model.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return $this
     */
    public function setAttribute($key, $value)
    {
        # 检查修改器
        if ($this->hasSetMutator($key)) {
            $method = 'set'.Str::studly($key).'Attribute';
>
            return $this->{$method}($value);
        }
>
        # 处理日期类型
        elseif ($value && $this->isDateAttribute($key)) {
            $value = $this->fromDateTime($value);
        }

>          #    处理对象类型
        if ($this->isJsonCastable($key) && ! is_null($value)) {
            $value = $this->castAttributeAsJson($key, $value);
        }
>
        # 处理json数据
        if (Str::contains($key, '->')) {
            return $this->fillJsonAttribute($key, $value);
        }
>
        $this->attributes[$key] = $value;
>
        return $this;
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!