(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`"
}

最新文章

  1. dcraw源码解析
  2. mvc 项目下 webservice 程序无法运行
  3. 【BZOJ】3319: 黑白树
  4. 另一个 SqlParameterCollection 中已包含 SqlParameter
  5. Delphi webservice 定义 转
  6. 调试Linq的时候获得相对应的SQL
  7. 行列转换之静态、动态、PIVOT方法
  8. Django 基础二(View和urls)
  9. vue报错Error in render: &quot;TypeError: Cannot read property &#39;0&#39; of undefined&quot;
  10. Git&amp;GitHub-进阶教程
  11. C++中,有哪4种与类型转换相关的关键字?各有什么特点?应该在什么场合下使用?
  12. 【独家】硅谷创业公司在中国常跌的五个坑|禾赛科技CEO李一帆柏林亚太周主题演讲
  13. php搜索附近人及显示男生女生分开
  14. hadoop集群中动态添加节点
  15. docker swarm英文文档学习-2-关键概念
  16. bzoj 4871: [Shoi2017]摧毁“树状图”
  17. DEDECMS去除后门隐患和漏洞以及冗余代码的方法
  18. Codeforces 1009D:Relatively Prime Graph
  19. vue环境中生成二维码
  20. day 6 老王开枪打人

热门文章

  1. Android之——jni通用工具方法
  2. iOS tableview cell 的展开收缩
  3. MySQLi 和 PDO 连接 MySQL
  4. iOS 特定图片的button的旋转动画
  5. 2015 Multi-University Training Contest 4 1001 Olympiad
  6. 【bzoj4542】[Hnoi2016]大数
  7. expand_dims
  8. YTU 2505: 啤酒和饮料
  9. YTU 2641: 填空题:静态成员---计算学生个数
  10. JFreeChart自我总结