$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 協議》,轉載必須註明作者和本文連結