ThinkPHP---thinkphp模型(M)拓展

(1)创建数据对象

数据对象就是父类模型中的$this->data,AR模式的底层数据操作用到了数据对象。模型实例化之前数据对象只是空数组,后来使用了魔术方法__set设置了数据对象的值。

上述流程可以得出,使用数据对象前必须先创建数据对象。__set是设置数据对象的一种方法,但是应用时不便,设置一个属性就得设置一行代码。

因此ThinkPHP中系统封装了批量设置数据对象的方法:create方法

语法:$model->create();

关于参数,这里去分析父类模型

public function create($data='',$type='') {
        // 如果没有传值,默认取POST数据
        if(empty($data)) {
            $data   =   I('post.');
        }elseif(is_object($data)){
            $data   =   get_object_vars($data);
        }
}

通过实现代码发现,若不给create方法传参,则默认使用post中的数据。在结尾,将处理完成的data数据赋值给了data属性,这步便是创建数据对象;将处理完成的数据返回出去,

谁调用返回给谁。

案例:改写之前编写的部门信息入库的代码,使用数据对象的创建方式。

//判断请求类型,若是post则提交,否则展示
            if (IS_POST) {
                //处理表单请求
                //成功接收后,写入数据
                $model = M('dept');//模型实例化
                // echo $_POST['name'];
                $data = $model->create();// 数据对象的创建需要模型去调用,所以必须放在实例化模型后(不传递参数,接收post数据)
                // dump($data);die;
                $result = $model->add();
                //判断返回值
                if ($result) {
                    $this->success('添加成功',U('showList'),3);
                }else{
                    $this->error('添加失败');//默认跳到上一页
                }
            }else{...}

注意:如表单中字段和数据表的字段不匹配,则创建数据对象时会被过滤掉。

如果想用打印方法查看数据是否正确,可以接收返回值。如果不想打印则可以不接受,在CURD操作时不需要给具体的操作方法传递参数。除非在使用自动验证时,必须接收

返回值。

(2)自动验证

①自定义规则:

   在提交数据时,系统按照指定规则进行数据的有效性和合理性验证。系统不知道表单的具体情况,所以没有想过规则,这也就需要我们自己去指定规则。

如果需要使用自动验证,规则需要自己去定义。

②验证:

    在前端的JS里的验证叫前端验证,在ThinkPHP里验证机制为后端 / 服务器验证。两者区别,因为js是在客户端的验证,所以可以完成无刷新的验证。而PHP是服务器端验证,

伴有刷新。除非用AJAX。

③语法:没有语法。。。由数据对象创建方法create方法去实现自动验证,这个在下面列出,我们需要做的就是指定相关验证规则。

Model.class.php
//
数据自动验证 if(!$this->autoValidation($data,$type)) return false;

所以综上可以得出,若想用自动验证则必须使用数据对象创建方法--create方法接收数据

④定义规则:

      在父类模型里存在成员属性_validate,这个属性是二维数组格式,用来保存验证规则

 // 查询表达式参数
    protected $_validate   =   array();  // 自动验证定义

由于不能在父类模型里直接更改属性,所以这里可以把属性赋值到子类自定义模型中去定义规则。

数据验证可以进行数据类型、业务规则、安全判断等方面的验证操作。

数据验证有两种方式:

  1. 静态方式:在模型类里面通过$_validate属性定义验证规则。
  2. 动态方式:使用模型类的validate方法动态创建自动验证规则。

无论是什么方式,验证规则的定义是统一的规则,定义格式为:

array(
     array(验证字段1,验证规则,错误提示,[验证条件,附加规则,验证时间]),
     array(验证字段2,验证规则,错误提示,[验证条件,附加规则,验证时间]),
     ......
);

必选参数:①验证字段:表单里每一个表单项的name值;

                  ②验证规则:针对验证字段的格式限制。require必须、email邮箱、number数字、URL地址、currentcy货币

                  ③错误提示:验证失败后的提示信息

可选参数:①验证条件:0默认,字段存在就验证;1必须验证;2字段不为空时验证。

                  ②附加规则:结合验证规则配合使用,具体方法可以参考手册

                  ③验证时间:分3种。新增数据时验证;编辑数据时验证;两者都验证

 

(3)案例:针对部门添加功能,使用自动验证来验证字段合法性

DempModel.class.php:

// 自动验证定义
        protected $_validate=array(
            //规则编写,参考手册
            // 1.针对部门名称规则
            array('name','require','部门名称不能为空'),//必填
            array('name','','部门名称已经存',0,'unique'),//不重复,这步会走数据库
            //2.针对排序验证
            array('sort','number','排序必须为数字'),//是否为数字,还可以使用函数function来验证
            // array('sort','is_numeric','排序必须是数字',0,'function');//函数名要求是函数库的或当前模型定义声明的
            array('remark','require','必须添加备注'),//备注必填
        );  

注意:因为这里是定义在了自定义模型里,所以实例化模型时需要实例化自定义模型。控制器DempController.class.php里修改

$model = D('dept');//模型实例化

①验证失败:

          此时提交空表单,输出返回值dump($data);die;浏览器输出false。为什么是false?这里我们可以看父类模型,因为这里返回false

// 数据自动验证
 if(!$this->autoValidation($data,$type)) return false;

②验证成功:如果验证成功,则返回正常数组

输出用户提示信息:$model->getError();

$model = D('dept');//模型实例化
                // echo $_POST['name'];
                $data = $model->create();// 数据对象的创建需要模型去调用,所以必须放在实例化模型后(不传递参数,接收post数据)
                if (!$data) {
                    // echo $model->getError();
                    $this -> error($model->getError());exit;//虽然理论上回跳回上一页,但PHP底层代码会继续执行。所以必须加exit
                }

 

(4)批量验证

一次性验证全部字段,需要配置成员属性

系统支持数据的批量验证功能,只需要在模型类里面设置patchValidate属性为true( 默认为false),

protected $patchValidate = true;

设置批处理验证后,getError() 方法返回的错误信息是一个数组,返回格式是:

array("字段名1"=>"错误提示1","字段名2"=>"错误提示2"... )

前端可以根据需要需要自行处理,例如转换成json格式返回:

$User = D("User"); // 实例化User对象
if (!$User->create()){
     // 如果创建失败 表示验证没有通过 输出错误提示信息
     $this->ajaxReturn($User->getError());
}else{
     // 验证通过 可以进行其他数据操作
} 

 

(3)字段映射

①映射表示对应关系

②应用场景:目前表单中的name值和数据表中的字段名一致,有一些人可能通过当前的功能和表单的name值猜测出表名字和表结构。后期可能会找到系统的漏洞,对系统进行

攻击。系统的安全性存在威胁。因此可以使用类似障眼法,将name值随机指定,这时name值和表字段不一致,那样也就猜测不出表结构了。

如果字段和数据表中的字段不匹配,会被系统过滤。所以需要有个对照列表,告知系统,不对应的name值是数据表的字段,防止字段被过滤。这时便用到了字段映射

③语法:没有语法、、、、只有规则定义$_map,与自动验证一样,在父类模型里有过定义

// 查询表达式参数
    protected $_validate        =   array();  // 自动验证定义
    protected $_map             =   array();  // 字段映射定义

将其复制到自定义子模型定义,

// 字段映射定义
 protected $_map=array(
      //映射规则,键是表单中的name值 = 值是表单中的字段名
     'abcde'=>'pid',
     'fghij'=>'sort'
); 

因为当前映射是建立在父类模型create方法里,所以在控制器里仍然需要create方式进行数据对象的创建

此时前端表单中替换name值,任然可以运行

pid:<input type="text" name="abcde"><br/>
sort:<input type="text" name="fghij"><br/>

在使用字段映射后,被映射的字段会被放到数组最后。按照字段映射的先后顺序进行排列。

 

(4)特殊表的实例化操作

 表没有前缀,或者表前缀不是配置文件里定义的前缀,这些都是特殊表

①新建一张特殊数据表szphp

②创建模型文件szphpModel.class.php

③szphp的实例化操作,D和M。按照之前操作实例化验证输出后报错:Table 'db_oa.sp_szphp' doesn't exist [ SQL语句 ] : SHOW COLUMNS FROM `sp_szphp`

 实例化时会将前缀和表名自动连接起来,所以会报错提示sp_szphp表不存在。

   解决办法:看下父类模型文件关于数据表名的定义

 // 数据表名(不包含表前缀)
  protected $tableName        =   '';
  // 实际数据表名(包含表前缀)
  protected $trueTableName    =   '';//告知系统当前模型所关联的表的真实表名,且是已经包含前缀的表名

这里我们选第二个,告诉ThinkPHP,这张表名已经包含前缀了,不要再加前缀。

通过父类模型属性中的成员属性trueTableName属性,进行表名的指定。告知模型表名真实名字,让其不要再关联上前缀。

输出$model结果

["model":protected] => string(5) "szphp"
    ["queryStr":protected] => string(25) "SHOW COLUMNS FROM `szphp`"//没有加前缀
    ["modelSql":protected] => array(1) {
      ["szphp"] => string(25) "SHOW COLUMNS FROM `szphp`"
    }

 

posted @ 2018-03-30 17:35  剑仙6  阅读(237)  评论(0编辑  收藏  举报
欢迎访问个人网站www.qingchun.在线