Skip to content

Eloquent: 变换器

介绍

访问器和变换器允许您在检索或设置模型实例上的Eloquent属性值时进行格式化。例如,您可能希望使用Laravel加密器在将值存储到数据库时加密它,然后在访问Eloquent模型上的属性时自动解密。

除了自定义访问器和变换器,Eloquent还可以自动将日期字段转换为Carbon实例,甚至可以将文本字段转换为JSON

访问器和变换器

定义访问器

要定义访问器,请在模型上创建一个getFooAttribute方法,其中Foo是您希望访问的列的“驼峰”命名。在此示例中,我们将为first_name属性定义一个访问器。尝试检索first_name属性的值时,Eloquent将自动调用访问器:

php
<?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属性:

php
$user = App\User::find(1);

$firstName = $user->first_name;

您还可以使用访问器从现有属性返回新的计算值:

php
/**
 * 获取用户的全名。
 *
 * @return string
 */
public function getFullNameAttribute()
{
    return "{$this->first_name} {$this->last_name}";
}
lightbulb

如果您希望将这些计算值添加到模型的数组/JSON表示中,您需要将它们附加

定义变换器

要定义变换器,请在模型上定义一个setFooAttribute方法,其中Foo是您希望访问的列的“驼峰”命名。同样,我们为first_name属性定义一个变换器。当我们尝试在模型上设置first_name属性的值时,将自动调用此变换器:

php
<?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

php
$user = App\User::find(1);

$user->first_name = 'Sally';

在此示例中,setFirstNameAttribute函数将以值Sally被调用。变换器将应用strtolower函数到名称并在内部$attributes数组中设置其结果值。

日期变换器

默认情况下,Eloquent会将created_atupdated_at列转换为Carbon实例,Carbon扩展了PHP的DateTime类并提供了一系列有用的方法。您可以通过设置模型的$dates属性来添加其他日期属性:

php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 应该被转换为日期的属性。
     *
     * @var array
     */
    protected $dates = [
        'seen_at',
    ];
}
lightbulb

您可以通过将模型的公共$timestamps属性设置为false来禁用默认的created_atupdated_at时间戳。

当某列被视为日期时,您可以将其值设置为UNIX时间戳、日期字符串(Y-m-d)、日期时间字符串或DateTime/Carbon实例。日期的值将被正确转换并存储在您的数据库中:

php
$user = App\User::find(1);

$user->deleted_at = now();

$user->save();

如上所述,当检索列在您的$dates属性中列出时,它们将自动被转换为Carbon实例,允许您在属性上使用Carbon的任何方法:

php
$user = App\User::find(1);

return $user->deleted_at->getTimestamp();

日期格式

默认情况下,时间戳格式为'Y-m-d H:i:s'。如果您需要自定义时间戳格式,请在模型上设置$dateFormat属性。此属性决定了日期属性在数据库中的存储方式,以及模型序列化为数组或JSON时的格式:

php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * 模型日期列的存储格式。
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

属性类型转换

模型上的$casts属性提供了一种将属性转换为常见数据类型的便捷方法。$casts属性应该是一个数组,其中键是要转换的属性的名称,值是您希望将列转换为的类型。支持的转换类型有:integerrealfloatdoubledecimal:<digits>stringbooleanobjectarraycollectiondatedatetimetimestamp。转换为decimal时,您应该定义数字位数,例如decimal:2

例如,让我们将is_admin属性(在数据库中存储为整数01)转换为布尔值:

php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 应该被转换为本机类型的属性。
     *
     * @var array
     */
    protected $casts = [
        'is_admin' => 'boolean',
    ];
}

现在,当您访问is_admin属性时,它将始终被转换为布尔值,即使底层值在数据库中存储为整数:

php
$user = App\User::find(1);

if ($user->is_admin) {
    //
}

数组和JSON类型转换

array转换类型在处理存储为序列化JSON的列时特别有用。例如,如果您的数据库有一个JSONTEXT字段类型,包含序列化的JSON,向该属性添加array转换将自动在您访问Eloquent模型上的属性时将其反序列化为PHP数组:

php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 应该被转换为本机类型的属性。
     *
     * @var array
     */
    protected $casts = [
        'options' => 'array',
    ];
}

一旦定义了转换,您可以访问options属性,它将自动从JSON反序列化为PHP数组。当您设置options属性的值时,给定的数组将自动序列化回JSON以进行存储:

php
$user = App\User::find(1);

$options = $user->options;

$options['key'] = 'value';

$user->options = $options;

$user->save();

日期类型转换

使用datedatetime转换类型时,您可以指定日期的格式。此格式将在模型序列化为数组或JSON时使用:

php
/**
 * 应该被转换为本机类型的属性。
 *
 * @var array
 */
protected $casts = [
    'created_at' => 'datetime:Y-m-d',
];