Eloquent: 修改器

简介

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

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

访问器 & 修改器

定义一个访问器

若要定义一个访问器,则须在你的模型上创建一个 getFooAttribute 方法。要访问的 Foo 字段需使用「驼峰式」来命名。在这个例子中,我们将为 first_name 属性定义一个访问器。当 Eloquent 尝试获取 first_name 的值时,将会自动调用此访问器:

  1. <?php
  2. namespace App;
  3. use Illuminate\Database\Eloquent\Model;
  4. class User extends Model
  5. {
  6. /**
  7. * 获取用户的名字。
  8. *
  9. * @param string $value
  10. * @return string
  11. */
  12. public function getFirstNameAttribute($value)
  13. {
  14. return ucfirst($value);
  15. }
  16. }

如你所见,字段的原始值被传递到访问器中,允许你对它进行处理并返回结果。如果想获取被修改后的值,你可以在模型实例上访问 first_name 属性:

  1. $user = App\User::find(1);
  2. $firstName = $user->first_name;

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

  1. /**
  2. * 获取用户姓名。
  3. *
  4. * @return string
  5. */
  6. public function getFullNameAttribute()
  7. {
  8. return "{$this->first_name} {$this->last_name}";
  9. }

定义一个修改器

若要定义一个修改器,则须在模型上定义一个 setFooAttribute 方法。要访问的 Foo 字段需使用「驼峰式」命名。让我们再来定义一个 first_name 属性的修改器。当我们尝试在模型上设置 first_name 的值时,该修改器将被自动调用:

  1. <?php
  2. namespace App;
  3. use Illuminate\Database\Eloquent\Model;
  4. class User extends Model
  5. {
  6. /**
  7. * 设定用户的名字。
  8. *
  9. * @param string $value
  10. * @return void
  11. */
  12. public function setFirstNameAttribute($value)
  13. {
  14. $this->attributes['first_name'] = strtolower($value);
  15. }
  16. }

修改器会获取属性已经被设置的值,允许你操作该值并将其设置到 Eloquent 模型内部的 $attributes 属性上。举个例子,如果我们尝试将 first_name 属性的值设置成 Sally

  1. $user = App\User::find(1);
  2. $user->first_name = 'Sally';

在这个例子中, setFirstNameAttribute 方法在调用的时候会接收 Sally 这个值作为参数。接着修改器会应用 strtolower 函数并将处理结果的值设置到内部的 $attributes 数组。

日期转换器

默认情况下,Eloquent 会把 created_atupdated_at 字段转换成 Carbon 实例, 它继承了 PHP 原生的 DateTime 类,并提供了各种有用的方法。你可以通过重写模型的 $dates 属性,自行定义哪些日期类型字段会被自动转换,或者完全禁止所有日期类型字段的转换:

  1. <?php
  2. namespace App;
  3. use Illuminate\Database\Eloquent\Model;
  4. class User extends Model
  5. {
  6. /**
  7. * 应被转换为日期的属性。
  8. *
  9. * @var array
  10. */
  11. protected $dates = [
  12. 'created_at',
  13. 'updated_at',
  14. 'deleted_at'
  15. ];
  16. }

当某个字段被认为是日期格式时,你或许想将其数值设置成一个 UNIX 时间戳、日期字符串(Y-m-d)、日期时间( date-time )字符串,当然还有 DateTimeCarbon 实例,并且让日期值自动正确地保存到你的数据库中:

  1. $user = App\User::find(1);
  2. $user->deleted_at = now();
  3. $user->save();

就如上面所说的,当获取到的属性包含在 $dates 属性中时,都将会自动转换成 Carbon 实例,允许你在属性上使用任意的 Carbon 方法:

  1. $user = App\User::find(1);
  2. return $user->deleted_at->getTimestamp();

日期格式

默认情况下,时间戳将会以 'Y-m-d H:i:s' 的形式格式化。如果你想要自定义时间戳格式,可在模型中设置 $dateFormat 属性。该属性决定了日期属性应以何种格式被保存到数据库中,以及当模型被序列化成数组 或 JSON 时的格式:

  1. <?php
  2. namespace App;
  3. use Illuminate\Database\Eloquent\Model;
  4. class Flight extends Model
  5. {
  6. /**
  7. * 模型中日期字段的保存格式。
  8. *
  9. * @var string
  10. */
  11. protected $dateFormat = 'U';
  12. }

属性类型转换

模型中的 $casts 属性提供了一个便利的方法来将属性转换为常见的数据类型。$casts 属性应是一个数组,且数组的键是那些需要被转换的属性名称,值则是你希望转换的数据类型。支持转换的数据类型有: integerrealfloatdoublestringbooleanobjectarraycollectiondatedatetimetimestamp

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

  1. <?php
  2. namespace App;
  3. use Illuminate\Database\Eloquent\Model;
  4. class User extends Model
  5. {
  6. /**
  7. * 应该被转换成原生类型的属性。
  8. *
  9. * @var array
  10. */
  11. protected $casts = [
  12. 'is_admin' => 'boolean',
  13. ];
  14. }

现在当你访问 is_admin 属性时,虽然保存在数据库里的的值是一个整数类型,但返回值总是会被转换成布尔值类型:

  1. $user = App\User::find(1);
  2. if ($user->is_admin) {
  3. //
  4. }

数组 & JSON 转换

当你在数据库存储系列化的 JSON 的数据时, array 类型转换非常有用. 例如, 如果你的数据库具有被序列化为JSON 的 JSONTEXT 字段类型 ,并且在 Eloquent 模型中加入了 array 类型转换 ,那么当你访问的时候就会自动被转换为 PHP 数组:

  1. <?php
  2. namespace App;
  3. use Illuminate\Database\Eloquent\Model;
  4. class User extends Model
  5. {
  6. /**
  7. * 这个属性应该被转换为原生类型.
  8. *
  9. * @var array
  10. */
  11. protected $casts = [
  12. 'options' => 'array',
  13. ];
  14. }

一旦定义了转换, 你访问 options 属性时它会自动从 JSON 类型反序列化为 PHP 数组 。当你设置 options 属性的值时,给定的数组也会自动序列化为 JSON 类型存储:

  1. $user = App\User::find(1);
  2. $options = $user->options;
  3. $options['key'] = 'value';
  4. $user->options = $options;
  5. $user->save();

Date 转换

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

  1. /**
  2. * 这个属性应该被转换为原生的类型.
  3. *
  4. * @var array
  5. */
  6. protected $casts = [
  7. 'created_at' => 'datetime:Y-m-d',
  8. ];

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

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接 我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。