ThinkPHP3.1数据CURD操作快速入门


Posted in PHP onJune 19, 2014

1.CURD概述:

CURD是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD。它代表创建(Create)、更新(Update)、读取(Read)和删除(Delete)操作。CURD 定义了用于处理数据的基本原子操作。之所以将CURD提升到一个技术难题的高度是因为完成一个涉及在多个数据库系统中进行CURD操作的汇总相关的活动,其性能可能会随数据关系的变化而有非常大的差异。

CURD在具体的应用中并非一定使用create、update、read和delete字样的方法,但是他们完成的功能是一致的。例如,ThinkPHP就是使用add、save、select和delete方法表示模型的CURD操作。

2.创建数据

大多数情况下,CURD的Create操作通常会通过表单来提交数据,首先,我们在项目的Tpl/Form目录下面创建一个add.html 模板文件,内容为:

<FORM method="post" action="__URL__/insert">
标题:<INPUT type="text" name="title"><br/>
内容:<TEXTAREA name="content" rows="5" cols="45"></TEXTAREA><br/>
 <INPUT type="submit" value="提交">
 </FORM>

然后,我们还需要在项目的Action目录下面创建一个FormAction.class.php文件,暂时只需要定义FormAction类,不需要添加任何操作方法,代码如下:

class FormAction extends Action{
 }

接下来,访问:

http://localhost/app/index.php/Form/add

就可以看到表单页面了,我们并没有在控制器里面定义add操作方法,但是很显然,访问是正常的。因为ThinkPHP在没有找到对应操作方法的情况下,会检查是否存在对应的模板文件,由于我们有对应的add模板文件,所以控制器就直接渲染该模板文件输出了。所以说对于没有任何实际逻辑的操作方法,我们只需要直接定义对应的模板文件就行了。
我们可以看到,在表单中定义了提交地址是到Form模块的insert操作,为了处理表单提交数据,我们需要在FormAction类中添加insert操作方法,如下:

class FormAction extends Action{
  public function insert(){
    $Form  =  D('Form');
    if($Form->create()) {
      $result =  $Form->add();
      if($result) {
        $this->success('操作成功!');
      }else{
        $this->error('写入错误!');
      }
    }else{
      $this->error($Form->getError());
    }
  }
 }

如果你的主键是自增类型的话,add方法的返回值就是该主键的值。不是自增主键的话,返回值表示插入数据的个数。如果返回false则表示写入出错。

3.模型

为了方便测试,我们首先在数据库中创建一个think_form表:

CREATE TABLE IF NOT EXISTS `think_form` (
 `id` smallint(4) unsigned NOT NULL AUTO_INCREMENT,
 `title` varchar(255) NOT NULL,
 `content` varchar(255) NOT NULL,
 `create_time` int(11) unsigned NOT NULL,
 PRIMARY KEY (`id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

我们在insert操作方法中用了D函数,和M函数不同,D函数需要有对应的模型类,下面我们就来创建模型类。模型类的定义规范是:
模型名+Model.class.php (模型名的定义采用驼峰法并且首字母大写)
我们在项目的Lib/Model 目录下面创建FormModel.class.php文件,添加代码如下:

class FormModel extends Model {
  // 定义自动验证
  protected $_validate  =  array(
    array('title','require','标题必须'),
    );
  // 定义自动完成
  protected $_auto  =  array(
    array('create_time','time',1,'function'),
    );
 }

主要是用于表单的自动验证和自动完成,具体用法我们会用另外的篇幅单独讲述,这里暂时先略过。我们只要了解的是,如果使用D函数实例化模型类,一般需要对应一个数据模型类,而且create方法会自动把表单提交的数据进行自动验证和自动完成(如果有定义的话),如果自动验证失败,就可以通过模型的getError方法获取验证提示信息,如果验证通过,就表示数据对象已经成功创建,但目前只是保存在内存中,直到我们调用add方法写入数据到数据库。这样就完成了一个完整的Create操作,所以可以看到ThinkPHP在创建数据的过程中使用了两步:

第一步,create方法创建数据对象,
第二步,使用add方法把当前的数据对象写入数据库。

当然,你完全可以跨过第一步,直接进行第二步,但是这样的预处理有几个优势:

1、无论表单有多复杂,create方法都可以用一行代码轻松创建数据对象;
2、在写入数据之前,可以对数据进行验证和补充;
其实create方法还有很多的功能操作,目的只有一个,确保写入数据库的数据安全和有效。

我们来验证下表单提交的效果,当我们不输入标题就直接提交表单的话,系统会给出标题必须这样的提示信息。
当我们顺利提交表单后,会看到写入数据表的数据中的create_time字段已经有值了,这就是通过模型的自动完成写入的。

如果你的数据完全是内部操作写入而不是通过表单的话(也就是说可以充分信任数据的安全),那么可以直接使用add方法,如:

$Form  =  D('Form');
$data['title'] =  'ThinkPHP';
$data['content']  =  '表单内容';
$Form->add($data);

也可以支持对象方式操作:

$Form  =  D('Form');
$Form->title =  'ThinkPHP';
$Form->content  =  '表单内容';
$Form->add();

对象方式操作的时候,add方法无需传入数据,会自动识别当前的数据对象赋值。

4.读取数据

当我们成功写入数据后,就可以进行数据读取操作了。在前面一篇中,我们已经知道可以用select方法获取数据集,这里我们来通过find方法获取一个单一数据,定义read操作方法如下:

public function read($id=0){
  $Form  =  M('Form');
  // 读取数据
  $data =  $Form->find($id);
  if($data) {
    $this->data =  $data;// 模板变量赋值
  }else{
    $this->error('数据错误');
  }
  $this->display();
 }

read操作方法有一个参数$id,表示我们可以接受URL里面的id变量(后面我们会在变量章节详细描述。这里之所以用M方法而没有用D方法,是因为find方法是基础模型类Model中的方法,所以没有必要浪费开销去实例化FormModel类(即使已经定义了FormModel类)。我们通常采用find方法读取某个数据,这里使用了AR模式来操作,所以没有传入查询条件,find($id) 表示读取主键为$id值的数据,find方法的返回值是一个如下格式的数组:

array(
  'id'    => 5,
  'title'   => '测试标题',
  'content'  => '测试内容',
  'status'  => 1,
 )

然后我们可以在模板中输出数据,添加一个read模板文件:

<table>
 <tr>
  <td>id:</td>
  <td>{$data.id}</td>
 </tr>
 <tr>
  <td>标题:</td>
  <td>{$data.title}</td>
 </tr>
 <tr>
  <td>内容:</td>
  <td>{$data.content}</td>
 </tr>
 </table>

完成后,我们就可以访问

http://localhost/app/index.php/Form/read/id/1

来查看了。
如果你只需要查询某个字段的值,还可以使用getField方法,例如:

$Form = M("Form"); 
 // 获取标题 
$title = $Form->where('id=3')->getField('title');

上面的用法表示获取id值为3的数据的title字段值。其实getField方法有很多用法,但是获取某个字段的值是getField方法最常规的用法。
查询操作是最常用的操作,尤其是涉及到复杂的查询条件,我们会在查询语言一章对查询进行更加详细的讲解。

5.更新数据

在成功写入并读取数据之后,我们就可以对数据进行编辑操作了,首先我们添加一个编辑表单的模板文件edit.html,如下:

<FORM method="post" action="__URL__/update">
  标题:<INPUT type="text" name="title" value="{$vo.title}"><br/>
  内容:<TEXTAREA name="content" rows="5" cols="45">{$vo.content}</TEXTAREA><br/>
  <INPUT type="hidden" name="id" value="{$vo.id}">
  <INPUT type="submit" value="提交">
 </FORM>

编辑模板不同于新增表单,需要对模板进行变量赋值,所以,我们这次需要在FormAction类添加两个操作方法:

public function edit($id=0){
  $Form  =  M('Form');
  $this->vo  =  $Form->find($id);
  $this->display();
 }
 public function update(){
  $Form  =  D('Form');
  if($Form->create()) {
    $result =  $Form->save();
    if($result) {
      $this->success('操作成功!');
    }else{
      $this->error('写入错误!');
    }
  }else{
    $this->error($Form->getError());
  }
 }

完成后,我们就可以访问

http://localhost/app/index.php/Form/edit/id/1

数据的更新操作在ThinkPHP使用save方法,可以看到,我们同样可以使用create方法创建表单提交的数据,而save方法则会自动把当前的数据对象更新到数据库,而更新的条件其实就是表的主键,这就是我们在编辑页面要把主键的值作为隐藏字段一起提交的原因。
如果更新操作不依赖表单的提交的话,就可以写成:

$Form = M("Form"); 
 // 要修改的数据对象属性赋值
$data['id'] = 5;
$data['title'] = 'ThinkPHP';
$data['content'] = 'ThinkPHP3.1版本发布';
$Form->save($data); // 根据条件保存修改的数据

save方法会自动识别数据对象中的主键字段,并作为更新条件。当然,你也可以显式的传入更新条件:

$Form = M("Form"); 
 // 要修改的数据对象属性赋值
$data['title'] = 'ThinkPHP';
$data['content'] = 'ThinkPHP3.1版本发布';
$Form->where('id=5')->save($data); // 根据条件保存修改的数据

也可以改成对象方式来操作:

$Form = M("Form"); 
 // 要修改的数据对象属性赋值
$Form->title = 'ThinkPHP';
$Form->content = 'ThinkPHP3.1版本发布';
$Form->where('id=5')->save(); // 根据条件保存修改的数据

数据对象赋值的方式,save方法无需传入数据,会自动识别。
save方法的返回值是影响的记录数,如果返回false则表示更新出错。

有些时候,我们只需要修改某个字段的值,就可以使用setField方法,而不需要每次都调用save方法。

$Form = M("Form"); 
 // 更改title值
$Form->where('id=5')->setField('title','ThinkPHP');

对于统计字段,系统还提供了更加方便的setInc和setDec方法。
例如:

$User = M("User"); // 实例化User对象
  $User->where('id=5')->setInc('score',3); // 用户的积分加3
  $User->where('id=5')->setInc('score'); // 用户的积分加1
  $User->where('id=5')->setDec('score',5); // 用户的积分减5
  $User->where('id=5')->setDec('score'); // 用户的积分减1

6.删除数据

删除数据很简单,只需要调用delete方法,例如:

$Form = M('Form');
$Form->delete(5);

表示删除主键为5的数据,delete方法可以删除单个数据,也可以删除多个数据,这取决于删除条件,例如:

$User = M("User"); // 实例化User对象
$User->where('id=5')->delete(); // 删除id为5的用户数据
$User->delete('1,2,5'); // 删除主键为1,2和5的用户数据
$User->where('status=0')->delete(); // 删除所有状态为0的用户数据

delete方法的返回值是删除的记录数,如果返回值是false则表示SQL出错,返回值如果为0表示没有删除任何数据。

PHP 相关文章推荐
dede3.1分页文字采集过滤规则详说(图文教程)续二
Apr 03 PHP
PHP自定义函数收代码
Aug 01 PHP
在WAMP环境下搭建ZendDebugger php调试工具的方法
Jul 18 PHP
PHP 小心urldecode引发的SQL注入漏洞
Oct 27 PHP
PHP 自定义错误处理函数trigger_error()
Mar 26 PHP
php结合ajax实现赞、顶、踩功能实例
May 12 PHP
php事件驱动化设计详解
Nov 10 PHP
PHP实现创建微信自定义菜单的方法示例
Jul 14 PHP
PHP实现浏览器中直接输出图片的方法示例
Mar 14 PHP
PHP结合jquery ajax实现上传多张图片,并限制图片大小操作示例
Mar 01 PHP
php+ajax实现商品对比功能示例
Apr 13 PHP
PHP查找一列有序数组是否包含某值的方法
Feb 07 PHP
ThinkPHP3.1.3版本新特性概述
Jun 19 #PHP
ThinkPHP访问不存在的模块跳转到404页面的方法
Jun 19 #PHP
解密ThinkPHP3.1.2版本之模块和操作映射
Jun 19 #PHP
解密ThinkPHP3.1.2版本之模板继承
Jun 19 #PHP
解密ThinkPHP3.1.2版本之独立分组功能应用
Jun 19 #PHP
ThinkPHP3.1新特性之对Ajax的支持更加完善
Jun 19 #PHP
php数组合并array_merge()函数使用注意事项
Jun 19 #PHP
You might like
symfony表单与页面实现技巧
2015/01/26 PHP
PHP基于SMTP协议实现邮件发送实例代码
2017/04/27 PHP
大家未必知道的Js技巧收藏
2008/04/07 Javascript
JS提交并解析后台返回的XML的代码
2008/11/03 Javascript
自己动手制作jquery插件之自动添加删除行功能介绍
2011/10/14 Javascript
jQuery隔行变色与普通JS写法的对比
2013/04/21 Javascript
jQuery点击弹出下拉菜单的小例子
2013/08/01 Javascript
javascript 获取浏览器版本
2015/01/21 Javascript
JS实现简单的键盘打字的效果
2015/04/24 Javascript
使用伪命名空间封装保护独自创建的对象方法
2016/08/04 Javascript
jquery easyUI中ajax异步校验用户名
2016/08/19 Javascript
JavaScript判断浏览器对CSS3属性是否支持的多种方法
2016/11/13 Javascript
Three.js基础学习之场景对象
2017/09/27 Javascript
百度地图去掉marker覆盖物或者去掉maker的label文字方法
2018/01/26 Javascript
Vue开发实现吸顶效果的示例代码
2018/08/21 Javascript
详解如何解决Vue和vue-template-compiler版本之间的问题
2018/09/17 Javascript
layUI的验证码功能及校验实例
2019/10/25 Javascript
JS中准确判断变量类型的方法
2020/06/01 Javascript
[01:47]2018年度DOTA2最佳教练-完美盛典
2018/12/16 DOTA
Python实现二分法算法实例
2015/02/02 Python
python3.5 tkinter实现页面跳转
2018/01/30 Python
Python 的字典(Dict)是如何存储的
2019/07/05 Python
将自己的数据集制作成TFRecord格式教程
2020/02/17 Python
Python3监控windows,linux系统的CPU、硬盘、内存使用率和各个端口的开启情况详细代码实例
2020/03/18 Python
pycharm 多行批量缩进和反向缩进快捷键介绍
2021/01/15 Python
巴西购物网站:Estrela10
2018/12/13 全球购物
分解成质因数(如435234=251*17*17*3*2,据说是华为笔试题)
2014/07/16 面试题
股份转让协议书范本
2015/01/27 职场文书
高考作弊检讨书1500字
2015/02/16 职场文书
2015年置业顾问工作总结
2015/04/07 职场文书
运动会广播稿20字
2015/08/19 职场文书
详解Go语言Slice作为函数参数的使用
2021/07/02 Golang
python接口测试返回数据为字典取值方式
2022/02/12 Python
Java线程的6种状态与生命周期
2022/05/11 Java/Android
Nginx利用Logrotate实现日志分割
2022/05/20 Servers
Java结构型设计模式之组合模式详解
2022/09/23 Java/Android