[ Laravel 5.8 文件 ] Eloquent ORM —— 訪問器和修改器
簡介
訪問器和修改器允許你在獲取模型屬性或設定其值時格式化 Eloquent 屬性。例如,你可能想要使用Laravel 加密器對儲存在資料庫中的資料進行加密,並且在 Eloquent 模型中訪問時自動進行解密。
除了自定義訪問器和修改器,Eloquent 還可以自動轉換日期欄位為Carbon 例項甚至將文字轉換為JSON。
訪問器 & 修改器
定義訪問器
要定義一個訪問器,需要在模型中建立一個getFooAttribute
方法,其中Foo
是你想要訪問的欄位名(使用駝峰式命名規則)。在本例中,我們將會為first_name
屬性定義一個訪問器,該訪問器在獲取first_name
的值時被 Eloquent 自動呼叫:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 獲取使用者的名字 * * @paramstring$value * @return string */ public function getFirstNameAttribute($value) { return ucfirst($value); } }
正如你所看到的,該欄位的原生值被傳遞給訪問器,然後返回處理過的值。要訪問該值只需要簡單訪問first_name
即可:
$user = App\User::find(1); $firstName = $user->first_name;
當然,你也可以使用訪問器將已存在的屬性轉化為全新的、經過處理的值:
/** * 獲取使用者的全名 * * @return string */ public function getFullNameAttribute() { return "{$this->first_name} {$this->last_name}"; }
注:如果你想要把這些計算值新增到以陣列/JSON格式表示的模型,需要手動追加它們。
定義修改器
要定義一個修改器,需要在模型中定義setFooAttribute
方法,其中Foo
是你想要訪問的欄位(使用駝峰式命名規則)。接下來讓我們為first_name
屬性定義一個修改器,當我們為模型上的first_name
賦值時該修改器會被自動呼叫:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 設定使用者的名字 * * @paramstring$value * @return string */ public function setFirstNameAttribute($value) { $this->attributes['first_name'] = strtolower($value); } }
該修改器獲取要被設定的屬性值,允許你操縱該值並設定 Eloquent 模型內部屬性值為操作後的值。例如,如果你嘗試設定Sally
的first_name
屬性:
$user = App\User::find(1); $user->first_name = 'Sally';
在本例中,setFirstNameAttribute
方法會被呼叫,傳入引數為Sally
,修改器會對其呼叫strtolower
函式並將處理後的值設定為內部屬性的值。
日期修改器
預設情況下,Eloquent 將會轉化created_at
和updated_at
列的值為Carbon
例項,該類繼承自 PHP 原生的Datetime
類,並提供了各種有用的方法。你可以自定義哪些欄位被自動調整修改,甚至可以通過重寫模型中的$dates
屬性完全禁止調整:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 應該被調整為日期的屬性 * * @var array */ protected $dates = [ 'seen_at' ]; }
注:你可以通過設定模型的公共屬性$timestamps
值為false
來禁止預設的created_at
和updated_at
時間戳。
如果欄位是日期格式時,你可以將其值設定為 UNIX 時間戳,日期字串(Y-m-d
),日期-時間字串,Datetime
/Carbon
例項,日期的值將會自動以正確格式儲存到資料庫中:
$user = App\User::find(1); $user->disabled_at = Carbon::now(); $user->save();
正如上面提到的,當獲取被羅列在$dates
陣列中的屬性時,它們會被自動轉化為Carbon
例項,並允許你在屬性上使用任何Carbon
類的方法:
$user = App\User::find(1); return $user->disabled_at->getTimestamp();
日期格式化
預設情況下,時間戳的格式是'Y-m-d H:i:s'
,如果你需要自定義時間戳格式,在模型中設定$dateFormat
屬性,該屬性決定日期屬性儲存在資料庫以及序列化為陣列或 JSON 時的格式:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * 模型日期的儲存格式 * * @var string */ protected $dateFormat = 'U'; }
屬性轉換
模型中的$casts
屬性為屬性欄位轉換到通用資料型別提供了便利方法 。$casts
屬性是陣列格式,其鍵是要被轉換的屬性名稱,其值時你想要轉換的型別。目前支援的轉換型別包括:integer
,real
,float
,double
,decimal:<digits>
,string
,boolean
,object
,array
,collection
,date
,datetime
和timestamp
。轉化為decimal
時,必須定義數字的位數(decimal:2
)。
例如,讓我們轉換is_admin
屬性,將其由integer
值(0
或1
)轉換為boolean
值:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 應該被轉化為原生型別的屬性 * * @var array */ protected $casts = [ 'is_admin' => 'boolean', ]; }
現在,is_admin
屬性在被訪問時總是被轉換為boolean
,即使底層儲存在資料庫中的值是integer
:
$user = App\User::find(1); if ($user->is_admin) { // }
陣列 & JSON 轉換
array
型別轉換在處理被儲存為序列化 JSON 格式的欄位時特別有用,例如,如果資料庫有一個JSON
或TEXT
欄位型別包含了序列化 JSON,新增array
型別轉換到該屬性將會在 Eloquent 模型中訪問其值時自動將其反序列化為 PHP 陣列:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 應該被轉化為原生型別的屬性 * * @var array */ protected $casts = [ 'options' => 'array', ]; }
型別轉換被定義後,訪問options
屬性將會自動從 JSON 反序列化為 PHP 陣列,反之,當你設定options
屬性的值時,給定陣列將會自動轉化為 JSON 以供儲存:
$user = App\User::find(1); $options = $user->options; $options['key'] = 'value'; $user->options = $options; $user->save();
日期轉換
當使用date
或datetime
轉換型別時,可以指定日期的格式,這個格式會在模型序列化為陣列或JSON時使用
:
/** * The attributes that should be cast to native types. * * @var array */ protected $casts = [ 'created_at' => 'datetime:Y-m-d', ];