# Eloquent: 修改器
- [簡介](#introduction)
- [訪問器 & 修改器](#accessors-and-mutators)
- [定義一個訪問器](#defining-an-accessor)
- [定義一個修改器](#defining-a-mutator)
- [日期轉換器](#date-mutators)
- [屬性類型轉換](#attribute-casting)
- [數組 & JSON 轉換](#array-and-json-casting)
<a name="introduction"></a>
## 簡介
當你在 Eloquent 模型實例中獲取或設置某些屬性值的時候,訪問器和修改器允許你對 Eloquent 屬性值進行格式化。例如,你可能想要使用 [Laravel 加密器](/docs/{{version}}/encryption) 來加密一個即將被保存在數據庫中的值,當你從 Eloquent 模型訪問該屬性時,其值將被自動解密。
除了自定義訪問器和修改器之外,Eloquent 也會自動將日期字段類型轉換成 [Carbon](https://github.com/briannesbitt/Carbon) 實例或將 [文本字段類型轉換成 JSON](#attribute-casting)。
<a name="accessors-and-mutators"></a>
## 訪問器 & 修改器
<a name="defining-an-accessor"></a>
### 定義一個訪問器
若要定義一個訪問器,則須在你的模型上創建一個 `getFooAttribute` 方法。要訪問的 `Foo` 字段需使用「駝峰式」來命名。在這個例子中,我們將為 `first_name` 屬性定義一個訪問器。當 Eloquent 嘗試獲取 `first_name` 的值時,將會自動調用此訪問器:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 獲取用戶的名字。
*
* @param string $value
* @return string
*/
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
}
如你所見,字段的原始值被傳遞到訪問器中,允許你對它進行處理并返回結果。如果想獲取被修改后的值,你可以在模型實例上訪問 `first_name` 屬性:
$user = App\User::find(1);
$firstName = $user->first_name;
<a name="defining-a-mutator"></a>
### 定義一個修改器
若要定義一個修改器,則須在模型上定義一個 `setFooAttribute` 方法。要訪問的 `Foo` 字段需使用「駝峰式」來命名。讓我們再來定義 `first_name` 屬性的修改器。當我們嘗試在模型上設置 `first_name` 的值時,該修改器將被自動調用:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 設定用戶的名字。
*
* @param string $value
* @return void
*/
public function setFirstNameAttribute($value)
{
$this->attributes['first_name'] = strtolower($value);
}
}
修改器會獲取屬性已經被設置的值,允許你操作該值并將其設置到 Eloquent 模型內部的 `$attributes` 屬性上。舉個例子,如果我們嘗試將 `first_name` 屬性設置成 `Sally`:
$user = App\User::find(1);
$user->first_name = 'Sally';
在這個例子中,`setFirstNameAttribute` 方法在調用的時候會接收 `Sally` 這個值作為參數。接著修改器會使用 `strtolower` 函數并將其值設置到內部的 `$attributes` 數組。
<a name="date-mutators"></a>
## 日期轉換器
默認情況下,Eloquent 將會把 `created_at` 和 `updated_at` 字段轉換成 [Carbon](https://github.com/briannesbitt/Carbon) 實例,它繼承了 PHP 原生的 DateTime 類,并提供了各種有用的方法。你可以通過重寫模型的 `$dates` 屬性,自行定義哪些日期類型字段會被自動轉換,或者完全禁止所有日期類型字段的轉換:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 應被轉換為日期的屬性。
*
* @var array
*/
protected $dates = [
'created_at',
'updated_at',
'deleted_at'
];
}
當某個字段被認為是日期格式時,你或許想將其數值設置成一個 UNIX 時間戳、日期字符串(`Y-m-d`)、日期時間( `date-time` )字符串,當然還有 `DateTime` 或 `Carbon` 實例,并且讓日期值自動正確地保存到你的數據庫中:
$user = App\User::find(1);
$user->deleted_at = Carbon::now();
$user->save();
就如上面所說的,當獲取到的屬性包含在 `$dates` 屬性時,都將會自動轉換成 [Carbon](https://github.com/briannesbitt/Carbon) 實例,允許你在屬性上使用任意的 `Carbon` 方法:
$user = App\User::find(1);
return $user->deleted_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';
}
<a name="attribute-casting"></a>
## 屬性類型轉換
`$casts` 屬性在模型中提供了一個便利的方法來將屬性轉換為常見的數據類型。`$casts` 屬性應是一個數組,且數組的鍵是那些需要被轉換的屬性名稱,值則是你希望轉換的數據類型。支持轉換數據類型有:
+ integer
+ real
+ float
+ double
+ string
+ boolean
+ object
+ array
+ collection
+ date
+ datetime
+ timestamp
例如,讓我們轉換 `is_admin` 屬性,將整數(`0` 或 `1`)轉換為布爾值:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 應該被轉換成原生類型的屬性。
*
* @var array
*/
protected $casts = [
'is_admin' => 'boolean',
];
}
現在當你訪問 `is_admin` 屬性時,它將會被轉換成布爾值類型,即便保存在數據庫里的的值是一個整數類型:
$user = App\User::find(1);
if ($user->is_admin) {
//
}
<a name="array-and-json-casting"></a>
### 數組 & JSON 轉換
如果一個字段是以被序列化的 JSON 來存儲在數據庫中, `array` 類型轉換將會非常有用。例如,當你在 Eloquent 模型上訪問的某個屬性在數據庫里是一個 `JSON` 或 `TEXT` 字段類型,它包含了被序列化的 JSON,而且你對該字段添加了 `array` 類型轉換,那么它將會自動反序列化成一個 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();
## 譯者署名
| 用戶名 | 頭像 | 職能 | 簽名 |
|---|---|---|---|
| [@Ucer](http://codehaoshi.com) | <img class="avatar-66 rm-style" src="https://dn-phphub.qbox.me/uploads/avatars/16042_1493680817.jpeg?imageView2/1/w/200/h/200"> | 翻譯 | Php 工程師,[Code好事](http://codehaoshi.com) |
---
> {note} 歡迎任何形式的轉載,但請務必注明出處,尊重他人勞動共創開源社區。
>
> 轉載請注明:本文檔由 Laravel China 社區 [laravel-china.org](https://laravel-china.org) 組織翻譯,詳見 [翻譯召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
>
> 文檔永久地址: https://d.laravel-china.org
- 說明
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- HomeStead
- Valet
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- 門面(Facades)
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- 重定向
- Session
- 表單驗證
- 錯誤與日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全
- 用戶認證
- API認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Passport OAuth 認證
- Scout 全文搜索
- Socialite 社交化登錄
- 交流說明