简介
当你在Eloquent模型实例中获取或设置某些属性值的时候,访问器和修改器允许你对Eloquent属性值进行格式化,访问器可在将要读取的数据进行处理后在返回给调用方,而修改器可在数据要被保存到数据库时进行一些相关处理,如清除表单提交的空格,时间格式化等
访问器
要定义一个访问器,则需在你的模型上创建一个getFooAttribute
方法。Foo
为要访问的属性,命名规则采用驼峰法,但访问这个属性时,又必须采用“驼峰一__驼峰二”(小写)
的方式访问,
如下例子
在我们的系统中,注册的用户可以设置昵称,当然这个昵称是可选的,当用户没有设置昵称则登录时就默认显示用户名,如果设置了昵称则登录时显示昵称,为了实现这个功能我们要定义一个访问器
在Muser
Model中定义一个访问器
//定义一个访问器,显示用户昵称public function getUserNickAttribute(){return $this->unick ? $this->unick : $this->uname;//如果有昵称,则返回昵称,如果没有昵称则将用户名设置成昵称}
访问访问器
调用访问器也很简单,只要我们遵从他的命名规则即可,以动态属性的方式访问
public function show(){$user = Muser::find(1); dump($user->user_nick);}
user_nick
对应于访问器方法名getUserNickAttribute()
的UserNick
成功返回用户昵称
如果用户没有昵称显示用户名
修改器
与访问器相反,修改器用于字段值保存到数据库之前进行一些相关处理,如加密,格式化等等,要定义一个修改器,则需在模型上定义一个setFooAtrribute
方法,要访问的Foo字段需使用驼峰式命名,命名规则与访问器一致
下面做一个简单的案例,通过修改器格式化用户输入的密码,并对其加密
1.定义一个user_password属性的修改器,当我们在模型上设置user_password的值时会自动触发修改器
public function setUserPasswordAttribute($value){$this->attributes['user_password'] = encrypt($value);}
2.设置用户密码,自动调用修改器
public function show(){$user = Muser::find(1);$user->user_password = 12345;$user->save();}
在本例中 我们设置属性user_password
触发了修改器(setUserPasswordAttribute()
),此时修改器会接受user_password
的值
12345作为参数传递到修改器中,接着修改器会通过encrypt
对其值进行加密,并传递到内部的$arrtibutes数组。
查看数据表
不过有一个问题
$user = Muser::where('uid',1)->update(['user_password'=>'fnfj']);
当运行上面的代码,触发修改器,然后对数据进行加密。没错吧
打开数据库查看数据是否被加密
很遗憾,数据并没有被加密,也就是更新时并没有触发修改器,这是为什么呢?
引用手册里的一句话
注:通过 Eloquent 进行批量更新时,saved 和 updated 模型事件将不会在更新模型时触发。
说人话就是当我们批量操作时是通过查询构造器而不是通过模型方法实现的,查询构造器不会触发模型事件,所以我们更新时没有触发修改器
日期转换器
默认情况下,Eloquent会把created_at和updated_at字段转换为Carbon实例,她继承了PHP原生的DateTime类,并提供了各种方法,你可以重写模型的$dates
属性,自行定义哪些日期类型字段会被自动转换,或者完全禁止所有日期类型字段的转换;
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class User extends Model
{/*** 应被转换为日期的属性。** @var array*/protected $dates = ['created_at','updated_at','add_time'];
}
当某个字段被认定为日期格式时,你想获得时间戳,日期字符串( Y-m-d
)或者日期时间字符串,当然还有 DateTime
或 Carbon
实例,并且让日期值自动正确地保存到你的数据库中
就如上面所说的,当获取到的属性包含在 $dates
属性时,都将会自动转换成 Carbon
实例,允许你在属性上使用任意的 Carbon
方法:
$user = App\User::find(1);$user->deleted_at = Carbon::now();$user->save();
$user = App\User::find(1);return $user->deleted_at->getTimestamp();
日期格式
默认情况下,时间戳将会以 ‘Y-m-d H:i:s’ 的形式格式化。如果你想要自定义自己的时间戳格式,可在模型中设置 $dateFormat 属性。该属性决定了日期属性应以何种格式被保存到数据表中,以及当模型被序列化成数组或是 JSON 格式时,这些日期属性以何种格式被保存:
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Flight extends Model
{/*** 模型的日期字段的保存格式。** @var string*/protected $dateFormat = 'U';
}
属性类型转换
casts属性在模型中提供方法将属性转换为常见的数据类型,casts属性在模型中提供方法将属性转换为常见的数据类型,casts属性在模型中提供方法将属性转换为常见的数据类型,cates属性为一个数组,键为要转换的属性,值为要转换的类型
常用转换类型如下
integer
real
float
double
string
boolean
object
array
collection
date
datetime
timestamp
如我们将flag
属性转换为布尔值,假定flag
字段存如数据库的是0或1
在模型定义属性$casts
protected $casts = ['flag' => 'boolean',];
当通过控制器访问属性flag
时,会自动转换为布尔型,但是数据库的值还是0或1
数组&JSON转换
当我们将数据以JSON格式存储在数据库时,每次存储肯定都有通过json_encode
进行解码,读取则要通过json_decode
进行编码,这样做是不是有点麻烦,Laravel中为我们提供了方便的办法,对于一个在数据库中类型为JSON
或TEXT
的字段,我们可以通过模型的$casts
属性
将对应字段设置转换为数组类型,这样在保存到数据库时,会自动转换为JSON格式,读取时则自动转换为php数组
做一个案例
1.新增一个字段json并设置数据类型为json格式
2.Model中设置json字段转换为数组
protected $casts = ['json'=>'array'];
3.测试保存操作
public function show(){$user = Muser::find(1);$user->json = ['name'=>'thh','sex'=>'N'];$user->save();}
打开数据库查看
可以看到数据确实被转换为json格式了
4.测试读取
public function show(){$user = Muser::find(1);dump($user->json);}