ThinkPHP3.2学习笔记3——模型、AR模式、辅助方法、统计查询
ThinkPHP中的模型
配置数据库的连接
数据库的连接配置项可以在系统的主配置文件ThinkPHP/Cof/convention.php中找到:
将上述的配置项复制粘贴到应用级别的配置文件Application/Common/Cof/config.php中(一般一个应用抵用给一个数据库):
//数据库设置
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => 'localhost', // 服务器地址
'DB_NAME' => 'itcast', // 数据库名
'DB_USER' => 'root', // 用户名
'DB_PWD' => 'root', // 密码
'DB_PORT' => '3306', // 端口
'DB_PREFIX' => '', // 数据库表前缀
数据库/表创建
数据库名:itcast
数据表名:student
什么是模型
模型是MVC三大组成部分的M(Model),作用是负责与数据表的数据交互(CURD)。
模型的创建
命名规范:模型名
(要求时候不带前缀的表名并且首字母大写)+Model.class.php
代码结构规范:
1. 声明命名空间;
2. 引入父类模型Model.class.php;
3. 声明模型并且继承父类模型;
例子:Application/Admin/Model/StudentModel.class.php
<?php
//声明命名空间
namespace Admin\Model;
//引入父类模型
use Think\Model;
//声明模型并继承父类模型
class StudentModel extends Model{
}
- 空模型继承了父类,所以可以进行数据表的基本操作。
模型的实例化操作
1. 普通的实例化方法
普通实例化方法是指通过自己编写方法来new一个对象。
语法格式:$obj=new 类名();
例子:在控制器中定义一个方法来实例化模型,使用的是普通方式实例化;
Application/Admin/Controller/StudentController.class.php
<?php
namespace Admin\Controller;
use Think\Controller;
class StudentController extends Controller{
//实例化模型
public function shilihua1(){
$model=new \Admin\Model\StudentModel();
dump($model);
}
}
2.快速实例化方法
在thinkPHP为了简单、快速、高效开发,为我们提供了2个快速方法可以对模型进行实例化操作:M方法和D方法。
D方法实例化
表示的含义:实例化我们自己创建的模型(分组/Model目录中)
语法格式:$obj=D(['模型名'])
- 如果传递了模型名,则实例化指定模型;如果没有指定模型名不存在,则直接实例化父类模型(Model.class.php)。
例子:
//快速实例化方法D
public function shilihua2(){
$model=D('Student');//实例化自定义模型
//$obj=D(); //直接实例化父类
dump($model);
}
M方法实例化
表示的含义:直接实例化父类模型(Think目录下的Model.class.php)
语法格式:$obj=M(['模型名'])
- 如果指定了表名,则直接指定实例化父类模型的时候关联指定的表,如果没有指定表名(没有传递参数)则不关联表;
- 一般用与执行原生sql语句(M()->query(原生的sql语句))
例子:
//快速实例化父类方法M
public function shilihua3(){
$model=M('Student');//实例化父类,关联数据表
//$obj=M(); //实例化父类,不关联数据表
dump($model);
}
D方法和M方法的区别
D方法是实例化自定义模型,如果自定义模型不存在,则实例化父类模型;
M方法本身就是直接实例化父类模型;
两者的差异就是实例化的对象不一样。
- 在后期开发中的怎么选择 使用D 方法或是M方法?
- 可以根据自身情况,如果需要使用的操作父类中已经封装好了。则可以直接实例化父类(使用M方法),如果父类中方法不能满足我们的开发需求,需要自己定义方法,则这个时候可以使用D方法实例化自定义模型。
CURD操作
CURD操作也就是模型操作数据表的基本操作。
C(Create)U(Update)R(Read)D(Delete)操作就是增删改查操作。
增加操作add()
在thinkPHP中,系统给我们封装好了模型中的方法,可以通过方法来实现数据的增加操作,这个方法叫做add方法。
语法格式:$model->add(一维数组);
返回值:新增主键的ID
- 一维数组必须是键值(关联)数组,键必须和数据表中字段名要匹配,如果不匹配日则在增加的时候会被thinkPHP过滤掉。
例子:
//add方法使用
public function tianjia(){
$model=M('Student');
$data=array(
'id' =>'1234567890',
'name'=>'cm',
'sex' =>'女',
'age' =>'20'
);
$result=$model->add($data);
dump($result);
}
添加多个记录addAll()
语法格式:$model->addAll(二维数组);
- 要求:最里面那层数组也是关联数组,外层数组必须是下标从0开始的连续索引数组。
- 需要注意的点太多,谨慎使用!
例子:
//addAll方法使用
public function tianjia2(){
$model=M('Student');
$datas=array(
array(
'id' =>'123',
'name'=>'cm',
'sex' =>'女',
'age' =>'20',
),
array(
'id' =>'0123',
'name'=>'cm',
'sex' =>'男',
'age' =>'21',
)
);
$result=$model->addAll($datas);
dump($result);
}
修改操作save()
语法格式:$model->save(一维关联数组);
返回值:受到影响的行数;
条件:需要一维关联数组必须要有主键信息,如果没有主键信息,则相当于批量修改,在thinkPHP中,系统为了防止误操作,不允许批量;
- 如果没有指定主键信息,则返回值是false,表示修改操作没有执行;
例子:
//save方法使用
public function xiugai(){
$model=M('Student');
$data=array(
'id' =>'001',
'name'=>'cm',
'sex' =>'女',
'age' =>'22'
);
$result=$model->save($data);
dump($result);
}
查询操作 select()和find()
select()方法
语法格式:
$model->select();
:表示查询全部信息;$model->select(id);
:表示查询指定id的信息;$model->select('id1,id2,id3...')
:表示查询指定的id集合的信息,等价于mysql中in语句
返回值:一个二维数组(即使查询的是一条记录,返回的也是二维数组);
例子:
//select方法使用
public function chaxun1(){
$model=M('Student');
$result=$model->select();
dump($result);
$result=$model->select(1608190208);
dump($result);
$result=$model->select('0000155,1608190208');
dump($result);
}
find()方法
语法格式:
$model->find();
:表示查询当前表中第一条记录,想当于limit 1;$model->find(id);
:表示查询表中的指定id的记录;
返回值:一维数组;
例子:
//find方法使用
public function chaxun2(){
$model=M('Student');
$result=$model->find();//第一个 limit 1
dump($result);
$result=$model->find(1608190208);
dump($result);
}
删除操作 delete()
语法格式:
$model->delete(id);
:表示删除指定id对应的记录;$model->delete('id1,id2,id3...');
:表示删除多个id对应的记录
例子:
//delete方法使用
public function shanchu(){
$model=M('Student');
$result=$model->delete(1608190208);
dump($result);
$result=$model->delete('0000155,1234567890');
dump($result);
}
数据对象的创建
数据对象就是父类模型中的$this->data
。
在模型实例化的时候,数据对象还是一个空数组,再后来使用了魔术方法__set来设置了数据对象的值------------------------>>> 使用数据对象对象时必须先创建数据对象。
在thinkPHP中系统提供了另外一种创建数据对象的create方法。
语法格式:$model->creat();
- 如果表单中字段和数据表中字段不匹配,则在创建数据对象的时候会被过滤掉。
自动验证
自动验证就是在提交数据的时候系统会按照指定的规则进行数据的有效性、合理性的验证。
上述提及的规则,系统默认是没有的,如果需要使用自动验证,规则需要我们自己去定义。
在前端中JavaScript的验证叫前端验证,在ThinkPHP中也存在验证机制,这样的验证称之为后端验证。
自动验证没有语法,由数据对象创建方法create方法去实现自动验证,那我们需要写的就是验证规则。
因为在create方法中执行了自动验证的处理 ,如果需要使用自动验证,则必须要用数据对象创建方法进行接收数据。
定义规则:protected $_validate = array();
编写规则(参考手册):
必选参数:
- 验证字段:表单中给每个表单项的name值。
- 验证规则:针对验证字段要求格式的限制,常见规则有require 字段必须、email 邮箱、url URL地址、currency 货币、number 数字。
- 提示信息:在验证不合理的时候给用户提示信息。
可选参数:
- 验证条件:0表示字段存在就验证(默认),1表示必须验证,2表示字段不为空时进行验证
- 附加规则:结合验证规则,两者配合起来使用。具体支持方法,参考手册。
- 验证时间:1表示新增数据的时候验证,2表示编辑的时候验证,3表示全部情况下都验证(默认)。
例子:针对部门添加功能,使用自动验证来验证字段的合法性。
说明:如果在自动验证中使用函数(function)来验证字段的合法性,则第二个参数要求是函数名(函数名要是函数是PHP内置函数或者自己定义的函数)
<?php
//声明命名空间
namespace Admin\Model;
//引入父类模型
use Think\Model;
//声明模型并继承父类模型
class StudentModel extends Model{
//自动验证定义
protected $_validate = array(
//针对部门名称的规则,必填,不能重复
array('name','require','部门名城能为空!'),
array('name','','部门已存在!',0,'unique'),
//排序字段的验证
//array('sort','number','排序必须是数字'),
//使用函数的方式来验证排序是否是数字
array('sort','is_numeric','排序必须是数字',0,'function'),
);
}
自动验证失败,则create方法返回false;如果验证成功,则返回正常的数组。
输出用户提示信息:$model->getError();
批量验证
需要配置成员属性:patchValidate设置成true,则表示开启批量验证。
<?php
namespace Admin\Model;
use Think\Model;
class StudentModel extends Model{
//开启批量验证
protected $patchValidate=true;
protected $_validate = array(
array('name','require','部门名城能为空!'),
array('name','','部门已存在!',0,'unique'),
array('sort','is_numeric','排序必须是数字',0,'function'),
);
}
字段映射
映射就是表示一个对应关系。
应用场景:在目前表单中的name值都和数据中的字段名都是一样的,有些人可能通过当前功能和表单的name值猜测出数据表的名字和表结构。后期可能会找到系统的漏洞对系统的进行功能、系统的安全性存在威胁。
将name值进行随机指定,name值就和表的字段不一致。
字段映射和自动验证一样没有语法,只有规则定义;
成员属性:$_map=array();
class StudentModel extends Model{
//开启批量验证
protected $patchValidate=true;
//字段映射定义
protected $_map =array(
//映射规则
//键是表单中的name值=值是数据表中的字段名
'abc' => 'name',
'wasd' => 'sort'
);
//自动验证定义
protected $_validate = array(
//针对部门名称的规则,必填,不能重复
array('name','require','部门名城能为空!'),
array('name','','部门已存在!',0,'unique'),
//排序字段的验证
//array('sort','number','排序必须是数字'),
//使用函数的方式来验证排序是否是数字
array('sort','is_numeric','排序必须是数字',0,'function'),
);
}
特殊表实例化
在实际开发中肯恩会遇到特殊表的情况,可能表会没有没有前缀、表的前缀不是在配置文件中定义的前缀。
模拟出一张特殊表:表名为szphp
创建模型文件:命名为SzphpMedel.class.php
通过父类属性中的成员属性trueTableName,进行表名的指定告知模型表名真实的名字是什么,让其不要再关联上前缀:
<?php
namespace Admin\Model;
use Think\Model;
class SzphpModel extends Model{
protected $trueTableName='szphp';
}
实例化模型:
public function test(){
$model=D('Szphp');
dump($model);
}
AR模式
介绍
AR模式即Active Record模式,是一个对象-关系映射(ORM)技术。每个AR类代表一张数据表(或视图)。数据表(或视图)的字段在AR类中体现为类的属性,一个AR实例则表示表中的一行。
AR模式的核心:三个映射/对应
AR类 —— 表 (模型类关联了表)
AR类的属性 —— 表的字段
AR类实例 —— 表的记录
AR模式在ThinkPHP中典型的应用:CURD操作。
AR模式的语法格式:
//实例化模型
$model=M(关联的表);
//字段映射到属性
$model->属性/表中字段=字段值;
$model->属性/表中字段=字段值;
...
//AR实例(操作)映射到表中记录
$model->CURD操作;//CURD操作没有参数
AR模式的CURD操作
增加操作
例子:
//AR模式增加操作
public function test23(){
//第一个映射:类映射表(类关联表)
$model=M('Student');
//第二个映射:属性映射字段
$model->id='01';
$model->name='clm';
$model->sex='女';
$model->age='22';
//第三个映射:实例映射记录
$result=$model->add();//没有参数
dump($result);
}
修改操作
注意:不管是直接通过save方法传递数组,还是使用AR模式,修改时候的主键必须需要。
例子:
//AR模式修改操作
public function test24(){
//实例化模型
$model=M('Student');
//属性映射到字段
$model->id='01';//确定主键信息
$model->sex='nv';//修改的信息
//修改操作
$result=$model->save();
dump($result);
}
查询操作
在thinkPHP中,AR模式没有查询操作,这里的查询操作还是使用之前的select和find方法。
删除操作
例子:
//AR模式删除操作
public function test25(){
//实例化模型
$model=M('Student');
//制定主键信息
$model->id='01,2';//属性可以指定1个主键也可以指定多个主键
//删除操作
$result=$model->delete();
dump($result);
}
- 在AR模式中U、D操作必须指定主键信息,但是有一种情况下可以不指定主键也嫩根治性U、D操作: 在之前有做过查询语句,则后面如果没有指定主键,会操作当前查询到的记录。
例子如下:
//AR模式可以不指定主键信息
public function test26(){
//实例化模型
$model=M('Student');
//查询
$data=$model->find(16);
//修改
//$model->name='cql';
//$result=$model->save();
//删除
$result=$model->delete();
dump($result);
}
辅助方法
- where----表示限制查询的条件
- limit-------表示限制输出的条数
- field-------表示限制输出的字段,也就是select id,name这样的语法
- order-----表示按照指定的字段进行指定的排序
- group----表示按照指定的字段进行分组查询
1.where方法
作用:限制查询的条件。
在原生的sql的语句中:select 字段 from 表 where 条件;
语法格式:
$model->where(条件表达式);//在thinkPHP中条件表达式支持字符串形式也支持数组形式,推荐使用字符串形式
$model->CURD操作;
例子:
//where方法
public function test27(){
$model=M('Student');
//查询
$model->where('id=01');//条件whereid=01
$data=$model->select();
dump($data);
}
2.limit方法
作用:限制输出的条数。(典型的应用:数据分页)
在原生的sql语句中:select 字段 from 表 where 条件 limit 限制的条数;
语法格式1:$model->limit(n);
n表示大于0的数字,表示输出表中的前n行
语法格式2:$model->limit(起始位置,偏移量/长度);
表示从第起始位置开始,往后查询指定长度的记录数,在实际使用的时候该种方法还支持写成$model->limit('起始位置,偏移量');
- 后期使用的分页效果其实就是使用的limit的第二种语法格式。
例子:
//limit方法
public function test28(){
$model=M('Student');
//第一种:查询n条
$model->limit(3);
$data=$model->select();
//第二种查询带偏移量的形式
$model->limit(1,3);
$model->select();
dump($data);
}
3.field方法
作用:限制输出的结果集字段。
在原生的sql语句中:select 字段1,字段2,字段3 [as 别名] form 表名;
语法格式:$model->field('字段1,字段2,字段3[ as 别名]...')
- 参数也就是select之后到from之前的那一串字符串。
例子:
//field方法
public function test29(){
$model=M('Student');
//限制字段
$model=field(id,name);
$data=$model->select();
dump($data);
}
==说明:上述三方法在父类模型中是真实存在的。==
## 4.order方法 作用:按照指定的字段进行指定规则的排序。 在原生的sql语句中:... order by字段 排序规则(升序asc/降序desc)。
语法格式:$model->order('字段名 排序规则');
例子:
//order方法
public function test30(){
$model=M('Student');
//排序
$model->order('id desc');//按照id降序排序
$data=$model->select();
dump($data);
}
5.group方法
作用:分组查询。
在原生的sql语句中:… group by 字段名;
语法格式:$model->group('字段名');
例子:
//group方法
public function test31(){
$model=M('Student');
//设置限制查询
$model->field('name,count(*) as count');
$model->group('name');
$data=$model->select();
dump($data);
}
==说明:上述两方法(order、group)在父类模型中是不存在的,通过魔术方法__call来实现后续的处理。==
## 连贯操作 连贯操作:就是将辅助方法全部写在一行上的写法,这样的形式叫做连贯操作。 原因:每个辅助方法最后返回值都是`$this`,而`$this`是指当前的模型类,由模型类去调用后续的辅助方法。
形式:$model->where()->limit()->order()->field()
->CURD操作;
- 注意:辅助方法的顺序在连贯操作中没有要求,只要符合模型在最前面CURD操作在最后面即可。
例子:
//连贯操作
public function test32(){
$model=M('Student');
//设置限制查询的连贯操作
$data=$model->field('name,count(*) as count')->group('name')->select();
dump($data);
}
ThinkPHP中的统计查询
- count()—表示查询表中总的记录数
- max()-----表示查询某个字段的最大值
- min()------表示查询某个字段的最小值
- avg()------表示查询某个字段的平均值
- sum()-----表示求出某个字段的总和
1.count方法
语法格式:$model[->where]->count();
返回值:string
例子:
//count方法
public function test33(){
$model=M('Student');
$count=$model->count();
dump($count);
}
2.max方法
语法:$model->max('字段名');
返回值:string
例子:
//max方法
public function test34(){
$model=M('Student');
$max=$model->max('id');
dump($max);
}
3.min方法
语法:$model->min('字段名');
返回值:string
例子:
//min方法
public function test35(){
$model=M('Student');
$min=$model->min('id');
dump($min);
}
4.avg方法
语法:$model->avg('字段名');
返回值:string
例子:
//avg方法
public function test36(){
$model=M('Student');
$avg=$model->avg('id');
dump($avg);
}
5.sum方法
语法:$model->sum('字段名');
返回值:string
例子:
//sum方法
public function test37(){
$model=M('Student');
$sum=$model->sum('id');
dump($sum);
}