# 模型实战开发之模型使用技巧
> 本节课讲的模型实际上是就是常说的物理模型 (数据模型)
[TOC]
## 模型的建立
建立一个新模型很简单 详情参见
https://www.kancloud.cn/mikkle/thinkphp5_study/268682
~~~
namespace app\base\model;
use think\Model;
/**
* Created by PhpStorm.
* User: Mikkle
* Q Q:776329498
* Date: 2017/2/8
* Time: 1:01
*/
class AdminUser extends Base
{
protected $table = "my_admin_user";
}
~~~
>[info] 模型中使用中,我们根据自身情况继承Base基类或者子基类,在模型中
> 模型中,只要定义好$table即可正常使用了.
## TP5模型最常用且实用的方法(写入部分)
### 模型的自动完成功能
>[success] 支持auto、insert和update三个属性,可以分别在写入、新增和更新的时候进行字段的自动完成机制,auto属性自动完成包含新增和更新操作
> 模型自动完成 只需要在model中定义三种对应的数组即可,注意未赋值的数组需要定义修改器
我们现在拿那个model实例说明一下:这个是半年前写的代码
点开下面链接查看全部代码
https://www.kancloud.cn/mikkle/thinkphp5_study/329928
~~~
protected $insert = ['status'=>1,'guid','order_no','order_state'=>0,'pay_type'=>0,'send_state'=>0,'is_comment'=>0,'factory_state'=>0];
~~~
大家看一下这段代码,我使用了 对象中$insert这个属性赋值,负责方式是数组.
>[danger] 当定义 $insert字段时,在写入时候模型会自动处理这些字段
> 当定义 $update字段时,在更新时候模型会自动处理这些字段
> 当定义 $auto字段时,在写入和更新时候模型都会自动处理这些字段
其中 guid 字段和order_no字段我并没有给出指定的值,那这时候会调用对应的修改器对该字段进行赋值
这个自动完成非常实用 特别是写入时候的自动完成($insert).
### 模型的修改器
>[danger] 模型的修改器作用是可以在数据赋值的时候自动进行转换处理
#### 修改器的实例
我们看一下自动完成中提到的 guid 字段和order_no字段的修改器
~~~
protected function setGuidAttr($value, $data)
{
return $this->create_uuid() ;
}
/**
* 订单类获取器 含防重复筛查
* Power by Mikkle
* QQ:776329498
* @param $value
* @param $data
* @return string
*/
protected function setOrderNoAttr($value, $data)
{
do {
$order_no= date('Ymd').$this->builderRand();
} while ($this->where('order_no',$order_no)->count()==1);
return $order_no ;
}
~~~
#### 模型修改器的建立方式
>[info] 修改器方法的命名规范为:setFieldNameAttr
我们只要在将字段转换成 大写驼峰 拼接在set. 和 Attr之间即可
| 字段名称 | 字段大写驼峰名称 |拼接后修改器对应方法名称 |
| --- | --- |--- |
| guid | Guid |setGuidAttr |
| order_no | OrderNo |setOrderNoAttr |
#### 修改器参数说明 $value, $data
| 值名称 | 参数说明 |值类型|
| --- | --- |--- |
| $value | 当前模型中对应字段传入的值 |--- |
| $data | 当前模型中对应字段传入的所有值 |数组 |
#### 修改器实例讲解
在订单模型创建新数据时候,我需要在给新数据赋值一个新的GUID以及唯一的数字型订单号,
这两个实例都未用到$value, $data两个参数,而使用到基类中的create_uuid builderRand
~~~
/**
* 创建个性GUID
* Power by Mikkle
* QQ:776329498
* @param string $base_code
* @return string
*/
public function create_uuid($base_code = '')
{
if (empty($base_code)) {
$base_name = basename(str_replace('\\', '/', get_called_class()), '.php');
$uuid_list = ModelCode::$uuid_list;
$base_code = isset($uuid_list[$base_name]) ? $uuid_list[$base_name] : 'QT';
}
$uuid = $base_code . strtoupper(uniqid()) . $this->builderRand(6);
return $uuid;
}
/**
* 创建随机数
* Power by Mikkle
* QQ:776329498
* @param int $num 随机数位数
* @return string
*/
public function builderRand($num=8){
return substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, $num);
}
~~~
>[info] 其中 create_uuid这个方法名不规范啊,现在要想改一下啊,不知道要动多少文件.
> (还有项目git中) 忍了吧 !大家千万别学我
> 另外 setOrderNoAttr 方法中,通过while方法进行查库比对 确保唯一
其实以前写个的这个方法也不严谨,存在可能发生的bug
~~~
do {
$order_no= date('Ymd').$this->builderRand();
} while ($this->where('order_no',$order_no)->count()==1); //bug 应该 count()>0;
return $order_no ;
~~~
如果数据库中如果已经出现重复,那查库验证就失效了!
好吧!我承认,我是专职写bug的!
#### 修改器的触发方法
修改器会在使用save方法触发
官方文档中也介绍了另一种触发方法
~~~
$user = new User();
$data['name'] = 'THINKPHP';
$data['email'] = 'thinkphp@qq.com';
$user->data($data, true);
$user->save();
echo $user->name; // thinkphp
~~~
>[info] 换句话说就是使用model新增和修改都会调用和使用的修改器
### 修改器使用注意事项即只读属性字段的应用
那么新的问题来了,当修改数据时候,如果传值有这两个字段数据时候,我们发现guid和order_no字段的全部变了.而且是修改一次变更一次.这两个字段可以说是重要索引字段 那么所有关联数据你猜会咋样
TP5的model方法 自读字段的设置 就最便捷的解决方法
> 不要问我 我是如何知道这个问题的,伤疤都快没有了,大家不要再揭了
#### 只读字段的定义
> 只读字段用来保护某些特殊的字段值不被更改,这个字段的值一旦写入,就无法更改。 要使用只读字段的功能,我们只需要在模型中定义readonly属性:
~~~
protected $readonly = ['guid','order_no'];
~~~
#### 只读字段放的位置
我的基类中有下面一行代码,一般人我不告诉他 嘿嘿
~~~
protected $readonly = ['guid'];
~~~
### 自动时间戳
>[info] **protected $autoWriteTimestamp = true;**
一句话的事情 ,我每个表基本都有
### 类型转换
这个我一直没有怎么用到
想了解的 请查看官方手册吧
https://www.kancloud.cn/manual/thinkphp5/138669
>[info] 模型中写入部分的常用的方法大体上 就这么多
再重申一下 一个是自动完成 一个修改器 还有一个只读字段 这三个方法是配合使用来完成数据的数据写入工作,
## TP5模型最常用且实用的方法(读取部分)
### 获取器的使用
>[info] 获取器的作用是在获取数据的字段值后按照我们定义的方法进行自动处理
#### 模型获取器的建立方式
>[info] 修改器方法的命名规范为:**getFieldNameAttr**
还是看order例子中的一段代码
~~~
public function getPayTypeAttr($value, $data){
if ($value){
$get_data = ['WxPay'=>'微信支付','AliPay'=>'支付宝支付'];
return isset($get_data[$value]) ? $get_data[$value] : '其他方式';
}else{
return $value;
}
}
public function getIsPayTextAttr($value, $data){
$get_data = ['0'=>'未付款','1'=>'已付款'];
return $get_data[$data['is_pay']];
}
~~~
我们只要在将字段转换成 大写驼峰 拼接在get. 和 Attr之间即可
| 字段名称 | 字段大写驼峰名称 |拼接后获取器对应方法名称 |
| --- | --- |--- |
| pay_type | PayType |getPayTypeAttr |
| is_pay_text | IsPayText |getIsPayTextAttr |
当字段中不存在的时候,我们随意append一个新字段,如果想获取is_pay的中文说明,就append写一个is_pay_text字段,并用$data中的值进行处理返回想要的值.
#### 获取器参数说明 $value, $data
| 值名称 | 参数说明 |值类型|
| --- | --- |--- |
| $value | 当前模型中对应字段读取的值 |--- |
| $data | 当前模型中读取的所有值 |数组 |
#### 获取器的触发方式
获取器只有当获取某个数据属性的时候自动触发,如果你要获取包含修改器处理的全部数据属性的话,可以使用下面的方法:
| 触发方法 | 触发方法实例 |
| --- | --- |
| 模型的数据对象取值操作 | $model->field_name |
| 模型的序列化输出操作 | $model->toArray() ;$model->toJson() |
| 显式调用getAttr方法 | $this->getAttr('field_name') |
| 附加字段要append | `$model->append(['field_name'])->toArray()` |
备注:定义修改器的字段 如果要获取原始数据的时候 使用下面官方文档中的方法
~~~
$user = User::get(1);
// 通过获取器获取字段
echo $user->status;
// 获取原始字段数据
echo $user->getData('status');
// 获取全部原始数据
dump($user->getData());
~~~
#### 获取器小结
>[danger] 获取器在项目中使用率比较高,我个人不建设使用和字段同名的获取器,而使用别名的获取器.
> 特别是项目进行中时候,你添加的同名获取器,可能会引发老代码bug
- 序言及更新日志
- 前言一 开发PHP必备的环境(你可以不看)
- LinUX系统ThinkPHP5链接MsSQL数据库的pdo_dblib扩展
- centos7.2挂载硬盘攻略
- Centos系统Redis安装及Redis的PHP扩展安装
- Centos系统增加Swap(系统交换区)的方法
- 前言二 开发PHP软件配置和介绍(你依然可以不看)
- 数据库SQL文件
- 本地Git(版本控制)的搭建
- GIT远程仓库的克隆和推送
- Git常用命令
- PHP面向对象思想实战经验领悟
- PHP面向对象实战----命名空间
- PHP面向对象实战----继承
- 基类实战--底层方法封装
- 基类实战--构造函数实战
- 基类实战--析构函数的使用
- TP5实战开发前篇---控制器(controller)
- 控制器中Request类的使用
- 控制器中基类的使用
- TP5实战开发前篇---模型篇(model)
- TP5实战开发前篇---验证器篇(Validate)
- TP5实战课程入门篇---花拳绣腿
- 模块以及类的文件的建立
- Api开发------单条信息显示
- Api开发---单条信息复杂关联显示
- Api开发---查询信息缓存Cache的应用
- TP5实战技巧---开发思路 引路造桥
- TP5实战技巧---整合基类 化繁为简
- TP5实战课程入门篇---数据操作
- Api开发---数据的添加和修改
- API开发---快速开发API通用接口
- TP5专用微信sdk使用教程
- THINKPHP5微信SDK更新记录及升级指导
- TP5专用SDK 微信参数配置方法
- 微信公众号推送接口对接教程
- 微信推送接口对接示例含扫描登录微信端部分
- TP5专用微信支付SDK使用简介
- TP5专用支付宝支付SDK使用说明
- 使用NW将开发的网站打包成桌面应用
- TP5高阶实战课程 进阶篇概述
- 进阶篇一 实战开发之习惯及要求
- 进阶篇二 实战开发之控制器
- 控制器基类之控制器基类使用方法
- 控制器基类之控制器基类常用方法分享
- 控制器基类之构造函数的使用方法
- 进阶篇三 实战开发之权限控制
- TP5实战源码 --- 全局用户信息验证类Auth
- TP5实战源码 --- 微信Auth实战开发源码
- 进阶篇四 实战开发之模型
- 模型基类之模型基类的用途
- 模型基类之常用数据处理方法
- 模型逻辑层之实战代码(含事务)
- 模型实战开发之模型常用方法
- 模型实战源码 --- 乐观锁的应用
- 模型实战技巧---Model事件功能的使用
- 模型事件实战应用---数据库操作日志
- 进阶篇五 实战开发之缓存(Cache)
- TP5实战源码---应用缓存获取城市信息
- TP5实战源码---应用缓存获取分类详情
- 进阶篇六 TP5类库的封装和使用
- DataEdit快捷操作类库
- ShowCode快捷使用类库
- 阿里大于 短信API接口 TP5专用类库
- DatabaseUpgrade数据库对比及更新类库
- AuthWeb权限类使用说明
- 进阶篇七 服务层的应用
- 服务层源码示例
- 服务层基类源码
- 进阶篇八 应用层Redis数据处理基类
- Redis服务层基类源码
- 进阶篇九 使用Redis类库处理一般的抢购(秒杀)活动示例
- 进阶篇十 某大型项目应用本Redis类源码示例(含事务 乐观锁)
- 进阶篇十一 逻辑层的应用
- 逻辑层基类源码
- 进阶篇 服务层代码示例
- 高阶实战课程 进阶篇持续新增中
- 高阶篇一 TP5命令行之守护任务源码
- TP5实战源码 --- 命令行
- TP5实战源码 --- 通过shell建立PHP守护程序
- 高阶篇二 使用Redis队列发送微信模版消息
- 高阶篇二 之 Worker队列基类源码
- 高阶篇三 TP5实战之Redis缓存应用
- Redis实战源码之Hash专用类库源码
- Redis实战源码之Model类结合
- Redis实战源码之模型Hash基类源码
- Redis实战源码之Hash查询使用技巧
- Redis实战源码之 shell脚本中redis赋值和取值
- 高阶篇四 Swoole的实战应用
- swoole基类代码
- Swoole扩展WebsocketServer专用类
- 基于Swoole的多Room聊天室的程序
- Swoole守护服务shell源码
- 高阶篇五 命令行异步多进程队列类的应用
- tp_worker类源码
- WorkerBase
- WorkerCommand
- WorkerRedis
- Redis类
- CycleWorkBase
- WorkerHookBase异步钩子
- 队列日志SQL
- 高阶篇六 定时执行队列类库以及使用方法
- 定时队列类库源码
- 高阶篇七 异步执行循环队列类库以及使用教程
- CycleWorkBase源码
- 高阶实战课程 进阶篇持续新增中
- Extend便捷类库源码库
- 阿里相关类库
- SendSms--验证码API接口文件
- 权限相关类库目录
- AuthWeb 权限验证类库
- Redis便捷操作类库(20171224更新)
- Redis
- Tools工具类库集
- Curl类库
- DataEdit
- Rand类库
- ShowCode类库
- Upload类库
- 附件集合
- 附件一:微信支付 实战开发源码
- 微信支付类库源代码
- Common_util_pub.php
- DownloadBill_pub.php
- JsApi_pub.php
- NativeCall_pub.php
- NativeLink_pub.php
- OrderQuery_pub.php
- Refund_pub.php
- RefundQuery_pub.php
- SDKRuntimeException.php
- ShortUrl_pub.php
- UnifiedOrder_pub.php
- Wxpay_client_pub.php
- Wxpay_server_pub.php
- WxPayConf_pub.php
- 微信支付回调页面源码
- 附件二 顺丰快递BSP接口实战开发源码
- 顺丰快递BSP接口实战开发源码
- 顺丰BSP基类
- 顺丰BSP基础代码
- 顺丰BSP下单接口
- 顺丰BSP查单接口
- 顺丰BSP确认/取消接口
- 附件三 APP注册登陆接口源码(含融云平台接口)
- 附件四 TP5订单Model(含事务 获取器 修改器等方法)
- 附录五 RSA加密解密
- Rsa文件源码
- 附件六 阿里大于短信接口
- 附件七 AES加解密类
- AES加解密类源码
- 附件八 TP5路由设置源码
- 附件九 TP5 Excel导入导出下载便捷类库
- Excel类库TP5源码
- 附件十 TP5便捷操作Redis类库源码
- TP5源码 Redis操作便捷类库
- 附件十一 TP5源码 上传文件入库类源码
- 上传类Upload源码
- Upload类上传配置文件
- 存储图像文件的数据库SQL文件
- 存储文件的数据库SQL文件
- 附件十二 TP5 图片处理增强类 支持缩略图在线显示
- 附件十三 微信推送消息接口类库源码
- 附件十三 微信推送消息接口类库源码 之 基类
- 附件十四 存储微信昵称的处理方法