定义获取器

获取器的作用是对模型对象的(原始)数据做出自动处理。一个获取器对应模型的一个特殊方法(该方法必须为public类型),方法命名规范为:getFieldNameAttr

FieldName为数据表字段的驼峰转换或者你数据表不存在的字段(注意理解后面这句话),下面是一个典型的获取器定义:<?php

namespace app\index\model;

use think\Model;

class User extends Model

{

public function getUserTypeAttr($value, $data)

{

$type = [0 => '普通', 1 => 'VIP', 2 => '黄金', 3 => '白金', 4 => '钻石'];

return $type[$value];

}

}

你需要给每一个需要输出转换处理的数据字段定义一个对应的获取器,但获取器的字段名不一定要和数据表的字段名一致,例如我希望给user_type字段定义一个名为getTypeAttr的获取器也是允许的,但要注意这个时候传入获取器的第一个参数肯定是没有值(因为没有对应的数据表字段数据),只能通过第二个参数获取你需要的数据。<?php

namespace app\index\model;

use think\Model;

class User extends Model

{

public function getTypeAttr($value, $data)

{

$type = [0 => '普通', 1 => 'VIP', 2 => '黄金', 3 => '白金', 4 => '钻石'];

return $type[$data['user_type']];

}

}

当然更为严谨的情况下,你还需要判断下是否存在$data['user_type'],这个暂且略过。注意第二个参数的data数据,可能本身已经经过了获取器的处理(如果你定义了相关的获取器的话)。

为什么要定义一个和数据报字段不一致的获取器呢?最明显的好处可以区分不同的字段获取原始数据和处理过的数据。事实上,有很多理由可以让你定义一些数据表不存在的字段获取器,这恰恰是获取器的魅力所在。

看的出来获取器定义本身没什么难度,关键在于方法里面的获取逻辑,这是实际应用中最需要关注的。

调用获取器

定义获取器之后会在下列情况自动触发:

·模型的数据对象取值操作(例如$model->field_name);

·模型的序列化输出操作(例如$model->toArray()或toJson());

·显式调用getAttr方法(例如$model->getAttr('field_name'));

前面两种其实最终都是调用最后一种来实现的,最关键的是要理解第一种。模型对象取值的时候一般都是通过下面的方式:$user = User::get(1);

echo $user->name;

echo $user->user_type;

当我们使用上面的方式进行模型对象数据获取或者在模板输出的时候事实上都会按照下面的顺序来检测和获取数据。

·第1步——如果查询结果包含该字段数据,取回原始数据,否则并进入第2步;

·第2步——检查是否定义该字段的获取器(包括动态获取器),如果有,则调用获取器返回结果,没有则进入第3步;

·第3步——检查是否定义了字段的类型转换,有则进行转换处理并返回结果,没有则进入第4步;

·第4步——如果是系统的时间字段,则自动进行时间格式化处理并返回结果,否则进入第5步;

·第5步——如果第1步检查的时候不包含该字段数据,则检查是否存在关联属性定义,有则通过关联关系获取数据并返回结果,否则抛出属性未定义的异常。上面的这五个步骤的详细代码,如果你有兴趣的可以直接参考think\model\concern\Attribute的getAttr方法代码。

简单来说,当你获取$user->user_type的时候都会去检查是否定义了相关的获取器,而不管user_type字段是否是一个真实的数据表字段。

但很多情况下,你不会一个个去获取模型数据,而是把整个模型数据返回给客户端或者模板。public function index()

{

$user = User::get(1);

return json($user);

}

在这种情况下,其实就是在响应输出的时候进行了模型的toJson处理。

有一点至关重要,如果你的获取器定义了非数据表的字段,是不会自动输出的,必须通过append方法追加额外属性(并且支持追加关联模型属性)。

如果我们定义了一个type属性的获取器(假设这并不是一个真实的数据表字段),那么需要使用下的方式才能正常输出(否则你可能只有user_type数据):public function index()

{

$user = User::get(1);

return json($user->append(['type']));

}

如果你是使用toArray的话,处理方式相同。

如果是数据集查询的话,一样可以使用append方法统一追加额外字段。public function index()

{

$users = User::all();

return json($users->append(['type']));

}除了append方法之外,我们还支持用hidden方法临时隐藏一些数据。

获取原始数据

有些情况下,除了要获取处理过的数据外,还需要获取原始数据以便应对不同的需求。

如果你的获取器都是用的区分于实际数据表字段的额外属性字段,那么这个问题本身已经解决了。所以我们主要讨论的是当你的获取器属性和数据表字段一致的情况下,该如何获取原始数据。

一个最简单的办法是使用getData方法:$user = User::get(1);

// 获取user_type获取器数据

echo $user->user_type;

// 获取原始的user_type数据

echo $user->getData('user_type');

// 获取全部原始数据

dump($user->getData());

动态获取器

前面我们提到过动态获取器的概念,动态获取器就是不需要在模型类里面定义获取器方法,而是在查询的时候使用闭包来定义一个字段的获取器对数据进行统一的处理。User::withAttr('name', function($value, $data) {

return strtolower($value);

})->select();

如果你需要定义多个动态获取器,多次调用withAttr方法就行。

动态获取器的意义除了可以不用在模型里面定义获取器方法之外,还可以起到覆盖已经定义的获取器的作用,并且动态获取器可以支持Db类操作,弥补了Db操作不能使用获取器的缺憾,具体就看自己的需求来选择了。Db::name('user')->withAttr('name', function($value, $data) {

return strtolower($value);

})->select();

总结

无论是获取器,还是之前提的修改器、搜索器,其作用无非是把你的模型工作细化和拆分,这样代码和逻辑也会更清晰,可维护性也大大增强,至于性能,从来不是模型首先考虑的。

PHP中文网,有大量免费的ThinkPHP入门教程,欢迎大家学习!

本文转自:https://blog.thinkphp.cn/825350

PHP查找第三大,ThinkPHP:模型三大利器之三(获取器)相关推荐

  1. 模型三大利器之三:获取器

    模型三大利器我们已经了解了修改器和搜索器,如果还不是特别理解的可以参考之前的博客. 今天来总结下获取器的用法,其实获取器是最容易理解的,但却又是最容易困惑和出问题的. 定义获取器 获取器的作用是对模型 ...

  2. 手把手带你从0完成医疗行业影像图像检测三大经典模型InceptionV3-RestNet50-VGG16(附python源代码及数据库)——改变世界经典人工智能项目实战(一)手把手教学迁移学习

    手把手带你从0完成医疗行业影像图像检测三大经典模型InceptionV3-RestNet50-VGG16 1.迁移学习简介 2.项目简介 3.糖尿病视网膜病变数据集 4.考虑类别不平衡问题 5.定义模 ...

  3. DSt:数据结构的简介、最强学习路线(逻辑结构【数组-链表-栈和队列/树-图-哈希】、物理结构、数据运算【十大排序/四大查找-图三大搜索-树三大遍历】、高级算法【贪心/分治/动态规划】之详细攻略

    DSt:数据结构的简介.最强学习路线(逻辑结构[数组-链表-栈和队列/树-图-哈希].物理结构[元素/关系].数据运算[十大排序/四大查找-图三大搜索-树三大遍历].高级算法[贪心/分治/动态规划]) ...

  4. dota自定义机器人队友_7.00新游记 三大英雄模型重制、自定义机器人

    全新版本--7.00新游记即将更新,DOTA2已将本次更新内容也已公布. 三大英雄模型重制: Dota英雄的生活已属不易,长相还频繁遭人吐槽.为了帮助游戏中服役时间最长的三名英雄重拾信心,本次更新还推 ...

  5. dota自定义机器人队友_DOTA2 7.00版本三大英雄模型重制 添加自定义机器人

    DOTA2 7.00版本三大英雄模型重制,添加自定义机器人,Dota英雄的生活已属不易,长相还频繁遭人吐槽.为了帮助游戏中服役时间最长的三名英雄重拾信心,本次更新还推出了斯拉达.冥界亚龙和谜团的重制模 ...

  6. thinkphp模型中的获取器和修改器(根据字段名自动调用模型中的方法)

    thinkphp模型中的获取器和修改器(根据字段名自动调用模型中的方法) 一.总结 记得看下面 1.获取器的作用是在获取数据的字段值后自动进行处理 2.修改器的作用是可以在数据赋值的时候自动进行转换处 ...

  7. thinkphp模型层Model、Logic、Service讲解

    thinkphp模型层Model.Logic.Service讲解 时间:2014-08-24 15:54:56   编辑:一切随缘   文章来源:php教程网 已阅读:771 次 js特效源码,就从这 ...

  8. tp3 php钩子函数,thinkphp模型事件(钩子函数:模型中在增删改等操作前后自动执行的事件)...

    thinkphp模型事件(钩子函数:模型中在增删改等操作前后自动执行的事件) 一.总结 1.通过模型事件(钩子函数),可以在插入更新删除等前后执行一些特定的功能 2.模型事件是写在模型里面的,控制器中 ...

  9. 【LLM】Langchain使用[一](模型、提示和解析器、存储)

    note 文章目录 note 零.LangChain介绍 一.模型.提示和解析器 1. 提示 2. 使用langchain写提示 3. 输出解析器 4. 链式思考推理(ReAct) 二.存储 1. 对 ...

最新文章

  1. 五十音图平假名流氓记忆(MD~!真难)
  2. Pat甲级 1002 A+B for Polynomials
  3. Modulus 正式开放 —— Node.js 应用托管平台
  4. MyBatis(4)动态SQL
  5. 辉光UIView的category
  6. 使用JPA标准@ViewScoped通过分页,过滤和排序进行Primefaces DataTable延迟加载
  7. Node.js -- Stream 使用小例 ( 流运用 :读取、写入、写出、拷贝)
  8. 使用android快速开发框架afinal的FinalDb操作android数据库
  9. linux查看xml文件的配置,Hibernate配置文件hibernate.cfg.xml的详细解释
  10. NTFS系统的访问控制上的权限条目
  11. MyBatis参数为Integer型并赋值为0时判断失误的问题解决
  12. ThingsBoard 开源技术体系总览
  13. java int转byte数组
  14. 中国土地市场销售规模状况与投资战略研究报告2022版
  15. 微型计算机存容量基本单位,在微型计算机中,存储容量的基本单位是什么?
  16. AR技术与VR技术有什么区别呢?
  17. ESP8266+Blinker+小爱同学舵机控制开关
  18. android沉浸式状态栏、fitsSystemWindows、标题栏折叠
  19. Centos7:网络设置+搜狗输入法安装
  20. 清华博士生导师亲授:高考志愿计算机/AI专业填报指南

热门文章

  1. html怎么引入本地css文件路径,html如何引入css文件
  2. 平台之战:京东,拿什么来跟天猫拼?
  3. 软件测试行业女生多么,软件测试行业为何女生越来越多?
  4. SLAM十四讲ch7代码调整(undefined reference to symbol)
  5. 【C#】磁盘信息获取
  6. 1岁以内的宝宝如何进行英文启蒙?
  7. linux until工具,Linux shell之until用法
  8. QQ截图图片不够清晰解决方法
  9. 战神 中文博客(附图)
  10. Ubuntu软件推荐