修改器

未匹配的标注
本文档最新版为 8.x,旧版本可能放弃维护,推荐阅读最新版!

Eloquent: 修改器

简介

当你在 Eloquent 模型实例中获取或设置某些属性值的时候,访问器和修改器允许你对 Eloquent 属性值进行格式化。例如,你可能需要使用 Laravel 加密器 来加密保存在数据库中的值,而在使用 Eloquent 模型访问该属性的时候自动进行解密其值。

除了自定义访问器和修改器外,Eloquent 也会自动将日期字段类型转换为 Carbon 实例,或将 文本类型转换为 JSON

访问器 & 修改器

定义一个访问器

若要定义一个访问器, 则需在模型上创建一个 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;

当然,你也可以通过已有的属性值,使用访问器返回新的计算值:

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

Tip:如果你需要将这些计算值添加到模型的数组 / JSON 中, 你需要追加它们.

定义一个修改器

若要定义一个修改器,则需在模型上面定义 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_atupdated_at 字段转换为Carbon实例,它继承了 PHP 原生的 DateTime 类并提供了各种有用的方法。你可以通过设置模型的 $dates 属性来添加其他日期属性:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

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

Tip:你可以通过将模型的公有属性 $timestamps 值设置为 false 来禁用默认的 created_atupdated_at 时间戳。

当某个字段是日期格式时,你可以将值设置为一个 UNIX 时间戳,日期时间(Y-m-d)字符串,或者 DateTime / Carbon 实例。日期值会被正确格式化并保存到你的数据库中:

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

$user->deleted_at = 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, realfloatdoubledecimal:<digits>string, booleanobject, arraycollectiondatedatetime, 和 timestamp。 当需要转换为 decimal 类型时,你需要定义小数位的个数,如: decimal:2

示例, 让我们把以整数(01 )形式存储在数据库中的 is_admin 属性转成布尔值。

    <?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 转换

当你在数据库存储序列化的 JSON 的数据时,array 类型的转换非常有用。比如:如果你的数据库具有被序列化为 JSON 的 JSONTEXT 字段类型,并且在 Eloquent 模型中加入了 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();

Date 转换

当使用 datedatetime 属性时,可以指定日期的格式。 这种格式会被用在 模型序列化为数组或者 JSON:

    /**
     * 这个属性应该被转化为原生类型.
     *
     * @var array
     */
    protected $casts = [
        'created_at' => 'datetime:Y-m-d',
    ];

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
Summer
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
贡献者:5
讨论数量: 5
发起讨论 只看当前版本


yuntian
xingxiaoli
对于转成 JSON 的字段获取时的疑问?
0 个点赞 | 13 个回复 | 问答 | 课程版本 5.8
Wen369367988
使用 在模型中使用 casts 怎么不会让中文转义
0 个点赞 | 3 个回复 | 问答 | 课程版本 5.7
oneSmile
可以动态启用 / 停用修改器吗?
0 个点赞 | 2 个回复 | 问答 | 课程版本 5.5
running8
多用访问器和修改器,少写了很多代码。
0 个点赞 | 0 个回复 | 分享 | 课程版本 5.5