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

ThinkPHP---thinkphp模型(M)拓展的更多相关文章

  1. thinkphp在模型中自动完成session赋值

    相信用过thinkphp的用户都知道thinkphp的模型可以完成很多辅助功能,比 如自动验证.自动完成等,今天在开发中遇到自动完成中需要获取session值 然后自动赋值的功能,具体看代码:clas ...

  2. ThinkPHP 关联模型(二十)

    原文:ThinkPHP 关联模型(二十) ThinkPHP关联模型 两表关联查询:Message 和  user  关联条件uid(参考手册:模型->关联模型) 步骤: 一:创建Message表 ...

  3. ThinkPHP框架模型连贯操作(八)

    原文:ThinkPHP框架模型连贯操作(八) Thinkphp的连贯操作使用起来也是很灵活: *可能这里有的mysql函数没全部罗列出来,大家可以举一反三,形式雷同 一.常用连贯操作 1.where ...

  4. ThinkPHP 的模型使用详细介绍--模型的核心(七)

    原文:ThinkPHP 的模型使用详细介绍--模型的核心(七) 注意:本节是ThinkPhp框架对数据操作的核心处理部分 大家还是在这里看清楚可以将其剪切放到代码编辑器中查看 本章节给大家着重介绍模型 ...

  5. ThinkPHP 的模型使用对数据库增删改查(五)

    原文:ThinkPHP 的模型使用对数据库增删改查(五) ThinkPHP 的模型使用 // 直接连接数据库,但是得先去配置文件中配置下才行 class IndexAction extends Act ...

  6. thinkphp 中模型究竟是什么用?

    thinkphp 中模型究竟是什么用? 问题 似乎所有的操作都能在控制器中就能完成,模型除了几种验证之外,究竟是干什么用的,这个问题一直没理解透 解答 解答一 要明白这个问题,必须了解 MVC 历史. ...

  7. ThinkPHP关联模型详解

    在ThinkPHP中,关联模型更类似一种mysql中的外键约束,但是外键约束更加安全,缺点却是在写sql语句的时候不方便,ThinkPHP很好得解决了这个问题.但是很多人不动关联模型的意思.现在就写个 ...

  8. ThinkPHP关联模型如何关联非主键

    ThinkPHP关联模型默认是主键外键关联 官方并没有提供相关文档 如何实现非主键与非主键间之间的关联 <?php namespace Admin\Model; use Think\Model\ ...

  9. ThinkPHP支持模型的分层

    ThinkPHP支持模型的分层 ,除了Model层之外,我们可以项目的需要设计和创建其他的模型层. 大理石平台支架 通常情况下,不同的分层模型仍然是继承系统的\Think\Model类或其子类,所以, ...

  10. ThinkPHP - 关联模型 - 一对多

    使用之前,先引入文件夹,否则相应的功能不能实现. 如果对thinkPHP不精通,使用或开发的时候,最好直接使用完成版本的ThinkPHP. 关系模型定义: <?php /** * 继承自 Rel ...

随机推荐

  1. Cocos2d-x编译Android环境

    1.Android环境搭配: 下载jdk 下载Android ADT 下载安装Android SDK,地址:http://developer.android.com/sdk/index.html#do ...

  2. MVC 登录后重定向来最初请求的 URL

    1.在登录的“Action” 方法中接收“ReturnUrl”参数. 2.在验证登录的“Action”方法中登录成功后,判断如果“ReturnUrl”不为空就跳转到“ReturnUrl”指向的页面. ...

  3. go17---并发

    yjf512 · 2015-02-21 11:09:07 · 1076 次点击 · 预计阅读时间 2 分钟 · 大约1分钟之前 开始浏览     这是一个创建于 2015-02-21 11:09:07 ...

  4. java jmenu的替代方案

    本来想实现一个类似jmenu的窗口,但是发现找了半天也没从L&F中找到实现menu的消失的头绪,最后还是使用了替代方案 使用JDialog来模拟一个menu的窗口,设置 setModel(fa ...

  5. Linux下 CentOS 7 对比6 改动详解 及 系统安装

    系统基础服务变化 操作系统 本文CentOS7 为最新版7.5 本文CentOS6 为6.9 操作 Centos6 Centos7 对比 自动补全 只支持命令.文件名 支持命令.选项.文件名 文件系统 ...

  6. [Swift]Array数组的swapAt函数

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  7. 字符类型C++(ascll码表)

    ascll码: 序号 字符 序号 字符 序号 字符 序号 字符 序号 字符 序号 字符 32 空格 48 0 64 @ 80 P 96 ` 112 p 33 ! 49 1 65 A 81 Q 97 a ...

  8. JavaScript--userAgent

    userAgent 返回用户代理头的字符串表示(就是包括浏览器版本信息等的字符串) 语法 navigator.userAgent 几种浏览的user_agent.,像360的兼容模式用的是IE.极速模 ...

  9. C#封装访问修饰符

    C# 封装 封装 被定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中".在面向对象程序设计方法论中,封装是为了防止对实现细节的访问. 抽象和封装是面向对象程序设计的相关特性. ...

  10. 安装Kali里的应用程序或软件包

    安装Kali里的应用程序或软件包 安装额外的软件是apt-get命令最基本的功能了,命令非常简单易懂.安装软件包的语法如下: apt-get install 软件包名 比如,安装图像编辑软件gimp, ...