模型中的事务处理

  1. 创建测试方法

    1. public function test15(){
    2. $model =D('goods');
    3. //开启事务
    4. $model->startTrans();
    5. $res = $model->where('id=5')->save(array('goods_name'=>'test15'));
    6. $res1 = $model->where('id=4')->save(array('goods_name'=>'test15'));
    7. dump($res);
    8. if($res !==false && $res1 !==false){
    9. $model->commit();//提交事务
    10. }else{
    11. $model->rollback();//事物回滚
    12. }
    13. }

    实例化模板对象

  2. 常规的实例化方法

image.png
具体效果:
image.png

  1. 使用Tp内置的M函数实例化对象

    1. public function test1(){
    2. /**
    3. * M默认有三个参数。在使用的过程中可以对三个参数都不传递或者传递某几个!
    4. * 第一个参数:指定具体的某一个数据表(默认没有前缀)
    5. * 第二个参数:指定具体的表前
    6. * 第三个参数:指定具体的mysql连接信息
    7. */
    8. //M函数是实例化TP的模型基类.对于目前没有传递参数。一般使用在需要直接使用原生SQL语句
    9. $model =M('Goods');
    10. //对于此方式指定了具体的操作的数据表。可以使用TP模型基类的具体方式进行数据操作
    11. dump($model);
    12. }

    效果:
    image.png

  2. 使用D函数实例化对象

image.png
效果:
image.png

  1. 总结关于M跟D区别

M永远实例化TP的模型的基类
D会优先实例化自定义的模型类。如果自定义额模型类不存在,就会实例化TP模型基类。

模型的CURD操作

CURD 即数据的增删改查操作。在TP中提供的模型基类中已经实现了数据的增、删、改、查等方法
在配置表中修改

  1. /* 数据库设置 */
  2. 'DB_TYPE' => 'mysql', // 数据库类型
  3. 'DB_HOST' => '127.0.0.1', // 服务器地址
  4. 'DB_NAME' => 'test', // 数据库名
  5. 'DB_USER' => 'root', // 用户名
  6. 'DB_PWD' => 'root', // 密码
  7. 'DB_PORT' => '3306', // 端口
  8. 'DB_PREFIX' => 't3_', // 数据库表前缀

数据写入

  1. add写入

    1. public function test4(){
    2. //实例化模型对象
    3. $model =D('Goods');
    4. //拼接具体要写入的数据
    5. //是需要使用add进行数据写入操作。
    6. //对于add是实现写入单条是数据,所以需要使用一维数组格式。下标对应具体的字段名称。
    7. //具体的值就是需要写入的内容
    8. $data = array(
    9. 'goods_name'=>'test4',
    10. 'addtime'=>time(),
    11. 'goods_body'=>'test4'
    12. );
    13. $res = $model ->add($data);
    14. dump($res);
    15. }
  2. addALL写入

    1. public function test5(){
    2. //实例化模型对象
    3. $model =D('Goods');
    4. //拼接具体要写入的内容
    5. /**
    6. * 当使用addAll实现写入多条数据时,需要将具体的数据设置为二维数组格式。
    7. * 每一个元素就对应具体的每一条数据。
    8. * 第一维下标需要使用从e开始的下标(0,1,2,3)
    9. */
    10. $data = array(
    11. array(
    12. 'goods_name'=>'test2',
    13. 'addtime'=>time(),
    14. 'goods_body'=>'test2'),
    15. array(
    16. 'goods_name'=>'test3',
    17. 'addtime'=>time(),
    18. 'goods_body'=>'test3'
    19. ),
    20. );
    21. $res = $model ->addAll($data);
    22. dump($res);
    23. }

    数据修改

  3. save 基本使用

使用save修改数据

  1. public function test6(){
  2. $model = D('Goods');
  3. //指定具体要修改的内容
  4. $data=array(
  5. 'gooods_name'=>'test6',
  6. );
  7. $res = $model->where('id=1')->save($data);
  8. dump($res);
  9. }
  10. public function test7(){
  11. $model = D('Goods');
  12. //指定具体要修改的内容
  13. $data=array(
  14. 'id'=>6,
  15. 'gooods_name'=>'test6',
  16. );
  17. $res = $model->save($data);
  18. dump($res);
  19. }

image.png

  1. setField 只更新个别字段

    1. public function test9(){
    2. //实例化模型对象
    3. $model =D('Goods');
    4. //setField作用实现更新具体某一些字段对应的内容
    5. //setField有两种使用方式
    6. //第一种可以直接给setField传递一个参数。需要使用数组格式。
    7. //要求是一个一维数组。下标为具体的字段名称。具体的值就是每一个字段对应要修改的内容
    8. //第二种可以对第一个参数指定具体的某一个字段名称。第二个参数为具体字段所对应要修改的内容
    9. //使用第一种方式实现修改多个字段值
    10. $model->where('id=5')->setField(array('goods_name'=>'test9','goods_body'=>'test9'));
    11. //使用第二种方法只修改一个字段
    12. $model->where('id=5')->setField(array('goods_name'=>'test8'));
    13. }
  2. setInc和setDec方法的使用

setInc:指定将某一个字段的值进行增加操作
setDec:指定将某一个字段的值进行减少操作
对于setInc跟setDec用法一模一样。都有两个参数。第一个参数需要指定具体的字段名称。第二个参数指定具体要增加或者减少的具体值。对于第二个参数可以不指定,如果不指定表示进行加一或者是减一

  1. public function test10(){
  2. $model = D('Goods');
  3. $model->where('id=6')->setInc('addtime');
  4. $model->where('id=5')->setDec('addtime');
  5. }

数据查询

Find:作用实现获取一条数据,返回的数据格式是一维数组
Select:作用实现获取多条数据,返回的数据格式是二维数组

  1. public function test11(){
  2. $model =D('Goods');
  3. //实现获取一条数据
  4. $res=$model->where('id=6')->find();
  5. dump($res);
  6. $res=$model->where('id=6')->select();
  7. dump($res);
  8. }

数据删除

  1. public function test12(){
  2. $model =D('Goods');
  3. $res=$model->where('id=1')->delete();
  4. $rss=$model->getLastSql();
  5. dump($res);
  6. dump($rss);
  7. }

数据表字段缓存

当直接使用Smodel->save(Sdata)时必须要指定要修改数据的主键才可以修改,TP为什么能知道具体哪一个字段是主键的呢?
每次实例化模型对象,TP都会分析对应数据表的字段信息,因此就可以知道具体哪一个才是主键字段

  1. 创建方法实例化模型对象

    1. //演示在实例化模型时有一个自动分析功能
    2. public function test13(){
    3. $model =D('Goods');
    4. dump($model);
    5. }

    解释什么时字段缓存

    将具体的字段信息存储到某一个文件中。当下次实例化会直接读取文件的信息。不会再去分析具体的数据表的结构

    开启字段换缓存模式

  2. 关闭调试模式

image.png

  1. 查看test13的效果

image.png

  1. 再次访问查看test13的效果

image.png
对于第一次访问。由于没有字段缓存的文件,因此TP还需要进行具体的字段分析操作。分析完毕之后会讲具体的结果保存到文件中。当下次再次访问时,不会再次分析数据表的结构信息。直接使用文件中所存储的内容即可
image.png
备注:在调试模式下,TP会每次都分析具体的字段结构信息(不论是否存在了字段缓存的文件)

数据表字段定义

在自定义的模型中将具体的字段信息保存到某一个具体的属性中(固定的属性名称)。本质也就是将具体的字段信息保存到变量中。变量会载入到内存。对于内存的速度比磁盘的速度要更加快。因此使用字段定义功能比字段缓存效果更加高

  1. 修改Goods模型 ```php

class GoodsModel extends Model{ //通过属性指定具体的主键字段信息 //protected $pk=’id’; //实现字段的定义功能 需要将每一个字段都写入到对应的数组中, //每一个字段就是一个具体的元素 protected $fields =array(‘id’,’goods_name’,’goods_img’,’addtime’,’goods_body’);

}

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26802498/1654054706055-e782c3f6-8ad6-47f0-8279-bc780b2ac9fa.png#clientId=u9b43f9f1-4e06-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=304&id=ubfa1aff6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=380&originWidth=589&originalType=binary&ratio=1&rotation=0&showTitle=false&size=102909&status=done&style=none&taskId=u6e1b9bec-a101-49a2-a7a7-40b50347dad&title=&width=471.2)
  2. <a name="pn9y2"></a>
  3. # 数据创建
  4. 使用模型对象调用create方法来自动的接受提交的数据内容并且对内容进行过滤操作(根据数据表的结构信息)。对于create功能非常多。<br />还可以出发很多的其他功能,例如自动验证<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/26802498/1654055380804-f731eb16-3c40-425c-bb70-56869a24577d.png#clientId=u9b43f9f1-4e06-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=532&id=u38332bb3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=665&originWidth=1100&originalType=binary&ratio=1&rotation=0&showTitle=false&size=491499&status=done&style=none&taskId=u7bdf031e-bc92-4823-ae9d-6627e1f3ded&title=&width=880)
  5. ```php
  6. public function add(){
  7. //需要add能够实现显示具体的表单以及实现能够处理表单的提交
  8. //为了实现该功能可以通过具体的请求方式进行区分,对于显示表单对应get方式的请求 表单提交 对应具体post方式的请求
  9. /*在TP中有很多的内置常量
  10. 其中有多个常量可以区分出具体的请求方式IS_GET:判断当前请求是否是get方式。
  11. 如果是get方式 该值为真
  12. IS_POST:判断当前请求是否是post方式。
  13. 如果是post方式该值为真 IS_AJAX:
  14. */
  15. if(IS_GET){
  16. $this->display();
  17. }else{
  18. $model =D('Goods');
  19. $data= $model->create(I('get.id'));
  20. dump($data);
  21. }
  22. }

字段映射

为了在表单中隐藏真实字段名称,可以使用假名。但是为了确保使用假名之后也能够使用数据的创建功能,可以在自定义的模型中通过某一个属性(有固定的名称)指定具体的假名与真名的对应关系。此方式就是字段映射

  1. 实现字段映射功能

使用假名称
image.png

  1. 查看效果

image.png
备注:字段映射默认是由create方法触发的。

自动验证

在使用create创建数据时自动对具体对提交的内容进行合法性的校验操作

验证规则

image.png
验证字段:需要在表单中验证的字段名称。可以是数据表中的字段名称也可以是表单中的辅助字段名称。例如验证码
验证规则:当附加规则指定使用哪一种方式进行验证验证规则会在附加规则的基础之上再次指定具体使用的规则。
当使用附加规则为regex,验证规则可以写上具体的正则表达式
当使用附加规则为function,验证规则可以写上具体的函数名称(PHP内置的函数名称、TP公共的函数名称、自定义的公共函数名称)
当使用附加规则为callback,验证规则可以写上具体当前模型类下具体的某一个方法的名称
错误提示:当验证不同时提示给用户的提示语
验证条件:控制当前的验证规则是否执行。
image.png
附加规则:指定当前的验证规则使用哪一种方式进行验证
image.png
image.png

  1. //增加属性指定具体的自动验证规则
  2. protected $_validate=array(
  3. array('goods_name','checkName','goods_name error',1,'callback'),
  4. array('goods_price','check_price','goods_name error',1,'callback'),
  5. array('goods_body','require','goods_name error',1,'callback'),
  6. );

修改goods模型

  1. public function checkName($goods_name){
  2. //根据商品名称的长度进行判断,要求长度大于3就不满足格式要求
  3. if(mb_strlen($goods_name,'utf8')>3){
  4. return false;
  5. }else{
  6. return true;
  7. }
  8. }

增加公共方法

  1. <?php
  2. //定义项目使用的公共函数 对于此文件下的函数会自动的载入到项目
  3. //检查当前提交的商品价格是否满足格式要求
  4. function check_price($goods_price){
  5. if($goods_price<=0){
  6. return false;
  7. }
  8. return true;
  9. }
  10. ?>

参数写法

  1. if(IS_GET){
  2. $this->display();
  3. }else{
  4. $model =D('Goods');
  5. $data= $model->create();
  6. if(!$data){
  7. //说明目前有数据格式不满足要求
  8. //$model->getError() 能够获取具体的错误信息
  9. dump($model->getError());
  10. }
  11. dump($data);
  12. }

自动完成

在使用create创建数据时TP会自动对接受的内容进行增加或者修改的操作

  1. 自动完成的使用场景

1、部分字段在表单没有体现出来(不需要用户进行录入操作),但是对于这些字段在数据的添加或者是修改时,又需要将具体对应的内容写入到数据库
2、使用create方法创建数据之后,可能部分数据在格式上不满足要求。就需要将具体的内容转换格式之后再写入到数据库。

  1. 自动完成方法

image.png

  1. 演示案例

    1. if(IS_GET){
    2. $this->display();
    3. }else{
    4. $model =D('Goods');
    5. $auto=(
    6. array('addtime','time',1,'function')
    7. );
    8. $data= $model->auto($auto)->create();
    9. if(!$data){
    10. //说明目前有数据格式不满足要求
    11. //$model->getError() 能够获取具体的错误信息
    12. dump($model->getError());
    13. }
    14. dump($data);
    15. }

    效果:
    image.png

    统计查询方法

  2. 查看统计查询方法

image.png

  1. 构造语句

    1. public function test14(){
    2. $model =D('Goods');
    3. //计算当前数据的总长度
    4. echo $model ->count();
    5. echo '<hr/>';
    6. echo $model->max('id');
    7. echo '<hr/>';
    8. //计算所有数据id的总值
    9. echo $model->sum('id');
    10. echo '<hr/>';
    11. //使用where指定具体得分条件进行统计查询
    12. echo $model->where("goods_name='test8'")->sum('id');
    13. }

    查看效果
    image.png
    image.png

    TP中的连贯操作

    连贯操作即在进行数据交互时使用多个方法顺序执行最后在调用一个CURD操作。
    连贯操作需要使用模型对象调用具体的连贯方法。可以调用一个也可以调用多个。每一个连贯方法调用没有任何的顺序。
    连贯操作使用格式:模型对象->连贯方法->curd方法
    最常用的连贯操作方法有where、field,alias、order,limit。

  2. 创建测试方法

    1. public function test16(){
    2. $model =D('Goods');
    3. //where,field,alias,order,limit field作用指定具体需要的字段信息中
    4. //关于field参数格式跟原生sql的格式一模一样
    5. $model ->field('id,goods_name')->select();
    6. echo $model->getLastSql().'<br>';
    7. //alias指定具体表的别名
    8. $model->alias('a')->field('id,goods_name')->select();
    9. echo $model->getLastSql().'<br>';
    10. //order 作用指定具体的排序方法
    11. $model->alias('a')->order('id desc')->field('id,goods_name')->select();
    12. echo $model->getLastSql().'<br>';
    13. //limit 限制具体的条数
    14. //使用有两种方法
    15. //1. 直接设置具体的数字,指定显示多少数据
    16. $model->alias('a')->order('id desc')->limit(3)->field('id,goods_name')->select();
    17. echo $model->getLastSql().'<br>';
    18. $model->alias('a')->order('id desc')->limit(1,2)->field('id,goods_name')->select();
    19. echo $model->getLastSql().'<br>';
    20. }

    链表查询

    1. public function test17(){
    2. //join方法能够实现连表查询功能
    3. //join指定具体的连表查询条件(具体的连接方式、具体需要连接哪一张数据表、具体的连接字段)
    4. $data=M('Stu')->alias('a')->field('a.*,b.class_name,b.class_room')
    5. ->join('left join shop_class b on a.class_id=b.id')->select();
    6. dump($data);
    7. }

    使用原生SQL语句

    1、Query:专门针对查询操作(select类型的SQL 语句)使用。返回具体的结果集
    2、Execute:专门针对写入操作(添加、修改、删除)使用。返回具体的受影响的行数
    对于上述两个方法使用时:模型对象->query/execute($sql);

    1. public function test18(){
    2. $model =M();
    3. $data = $model->query("select * from shop_stu");
    4. dump($data);
    5. $model->execute("insert into shop_stu value(null,1,'zhaoliu)");
    6. dump($data);
    7. }

    模型中狗子函数

    钩子函数即数据操作(写入、删除、修改b时会自动触发的方法。对于钩子函数区分前置跟后置之分。前置即数据在操作之前会执行,后置即在操作完成之后执行

    查看钩子函数的使用方法

    写入:_before_insert,_after_insert
    修改:_before_update,_after_update
    删除:_before_delete,after_delete
    image.png

    演示钩子函数的使用方式

  3. 创建测试方法

    1. public function test19(){
    2. $model=D('Goods');
    3. $res = $model->add(array('goods_name','test19'));
    4. }
  4. 修改模型类增加具体的钩子函数

    1. //数据写入的前置钩子函数
    2. public function _before_insert($data,$options){
    3. echo '_before_insert<hr/>';
    4. dump($data);
    5. dump($options);
    6. }
    7. //数据写入的后置钩子函数
    8. public function _after_insert($data,$options){
    9. echo '_after_insert<hr/>';
    10. dump($data);
    11. dump($options);
    12. }
  5. 测试

image.png