修改器是模型的三大利「器」之一,本篇我们来总结下修改器的用法,以及一些注意事项。
定义修改器
修改器的作用是在模型对象数据写入数据库之前进行一些必要的数据处理,修改器的标准定义如下:
public function setFieldNameAttr($value, $data) { // 对value值进行处理 data参数是当前全部数据 // 返回值就是实际要写入数据库的值 return $value; }
其中FieldName对应数据表的field_name字段(注意数据表字段的规范和修改器方法定义规范,否则会导致错误)。
原则上,每个修改器应当仅处理对应字段的数据,但在必要的情况下允许同时处理多个字段。
下面是一个例子
public function setBirthdayAttr($value, $data) { // 格式化生日数据 $birthday = strtotime($value); // 根据生日判断年龄 $age = getAgeByBirthday($birthday); // 赋值年龄数据 $this->setAttr('age', $age); return $birthday; } public function setAgeAttr($value,$data) { return floor($value); }
之所以使用setAttr方法是确保年龄赋值操作仍然可以走单独的修改器。如果你没有额外的修改器,那么也可以写成
public function setBirthdayAttr($value, $data) { // 格式化生日数据 $birthday = strtotime($value); // 根据生日判断年龄 $age = getAgeByBirthday($birthday); // 赋值年龄数据 $this->data['age'] = $age; return $birthday; }
注意一定不能写成
$this->age = $age;
因为在模型内部进行数据对象的赋值,会因为和模型内部属性混淆而导致不可预知的后果。
如果你在某个修改器中可能会对其它字段进行修改,务必记得你需要额外修改的字段修改器必须已经经过赋值操作(或者已经触发过修改器)。
如何调用
修改器方法不需要手动调用,按照定义规范定义好后,系统会在下面的情况下自动调用:
·模型对象赋值;
·调用模型的data方法,并且第二个参数传入true;
·调用模型的save方法,并且传入数组数据;
·显式调用模型的setAttr方法;
·定义了该字段的自动完成;
例如User模型定义了setPasswordAttr修改器方法。
public function setPasswordAttr($value, $data) { return md5($value); }
当下面这样使用的时候,保存到数据库的password字段的值就会变成md5('think')后的值。
$user = User::get(1); $user->password = 'think'; $user->save();
如果你在一些情况下,不希望使用修改器而是想要手动控制数据,可以尝试使用下面的方法。
$user = User::get(1); $user->data('password', md5('think')); $user->save();
这个时候就不会经过修改器处理。
避免冲突
很多开发者喜欢给修改器定义自动完成auto(包括insert和update)。
protected $auto = ['password'];
这在V5.1.27版本之前是一个看似聪明却非常致命的错误,要尽量避免,因为根据我们之前给出的修改器触发条件,会导致该修改器被执行两次。这会是一个灾难性的错误,将导致所有的用户注册后都无法正常登录。
解决办法取消password字段的自动完成设置,因为修改器会在每次赋值的时候自动触发,如果没有赋值说明密码没有被修改,也谈不上自动完成。
自动完成的字段通常是不在表单里面的字段,一般是由系统自动处理的字段。
V5.1.27版本改进了这个问题,所有的修改器只允许执行一次,上面的问题就不复存在了。但好像又带来了一个新的问题,很多时候,你也许想在模型的事件中对数据进行修改。
User::beforeUpdate(function($user) { $user->password = md5('think'); });
会发现,在模型beforeUpdate事件中,数据的值怎么都修改不了,原因是模型的修改器之前在第一次赋值的时候已经执行了,第二次再赋值的时候已经无效了(不会再执行)。
解决办法就是我前面提过的使用data方法不调用修改器进行数据赋值操作。
User::beforeUpdate(function($user) { $user->data('password', md5('think')); });
当然,更好的建议是规划好修改器、自动完成和模型事件的数据处理机制,不要对一个字段同时使用多重机制修改数据,并且写入数据库的数据应该并且只有修改器这一个途径进行数据修改操作。
类型自动转化
如果你的修改器仅仅是对数据做类型转换处理的话,可以无需定义修改器,而是直接定义字段类型就可以了。
public function setScoreAttr($value, $data) { return (float) $score; }
上面的修改器方法可以直接改成
protected $type = [ 'score' => 'float', ];
如果你同时对一个字段定义了修改器和类型的话,修改器是优先的。
类型定义不仅能定义简单的数据类型,还有一些额外的用途,例如:json 类型、array类型和object 类型会进行JSON序列化,serialize类型则会把数据进行serialize序列化。
PHP中文网,有大量免费的ThinkPHP入门教程,欢迎大家学习!
本文转自:https://blog.thinkphp.cn/817548
以上是ThinkPHP:模型三大利器之二(修改器)的详细内容。更多信息请关注PHP中文网其他相关文章!

本文讨论了ThinkPHP的内置测试框架,突出了其关键功能(例如单元和集成测试),以及它如何通过早期的错误检测和改进的代码质量来增强应用程序可靠性。

本文讨论了在无服务器体系结构中使用ThinkPHP的关键注意事项,专注于性能优化,无状态设计和安全性。它突出了诸如成本效率和可扩展性之类的收益,但也应对挑战

本文讨论了在ThinkPHP微服务中实施服务发现和负载平衡,重点是设置,最佳实践,集成方法和推荐工具。[159个字符]

ThinkPHP的IOC容器提供了高级功能,例如懒惰加载,上下文绑定和方法注入PHP App中有效依赖性管理的方法。Character计数:159

ThinkPHP具有轻巧的设计,MVC架构和可扩展性。它通过各种功能提高可扩展性,加快开发并提高安全性。

本文概述了使用ThinkPhp和RabbitMQ构建分布式任务队列系统,重点是安装,配置,任务管理和可扩展性。关键问题包括确保高可用性,避免常见的陷阱,例如不当


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

Dreamweaver CS6
视觉化网页开发工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),