Eloquent: 变换器
介绍
访问器和变换器允许您在检索或设置模型实例上的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
{
/**
* 获取用户的名字。
*
* @param string $value
* @return string
*/
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
}
如您所见,列的原始值被传递给访问器,允许您操作并返回该值。要访问访问器的值,您只需访问模型实例上的first_name
属性:
$user = App\User::find(1);
$firstName = $user->first_name;
定义变换器
要定义变换器,请在模型上定义一个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
数组中。
日期变换器
默认情况下,Eloquent会将created_at
和updated_at
列转换为Carbon实例,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
)、日期时间字符串,当然还有DateTime
/ Carbon
实例,日期的值将自动正确存储在您的数据库中:
$user = App\User::find(1);
$user->deleted_at = Carbon::now();
$user->save();
如上所述,当检索列在您的$dates
属性中列出时,它们将自动转换为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';
}
属性类型转换
模型上的$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) {
//
}
数组和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();