Laravel Model的$casts使用
$casts
是Model
提供的一个类型转换的数组,在使用该属性时,无论是设置数据还是获取数据,都将会把指定字段转换为指定的类型,但只在特定方式下有效:
示例类
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.使用Model
的fill()
函数填充属性时
$data = ['data' => ['test' => '这是数据']];
$model = app(Test::class)->fill($data)->save();
2.使用的Model
的update()
函数时
$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
属性做类型转换,因为他们都没有经过Model
的setAttribute
函数。
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 协议》,转载必须注明作者和本文链接