1、创建模型
- 1、存储位置
/应用/模块/Model目录
- 2、模型文件命名规则
名称+model+.class.php
首字母大写,驼峰写法
模型的作用是实现与数据库中的数据表进行具体的数据交互,一般要求模型名称跟对应的数据表的名称保持一致。也可不一致,但不推荐,应为模型本身就是用来操作数据表的。
- 2、模型代码创建规则
先设置命名空间
引入tp模型基类
创建自定义的模型类并且要继承tp的模型基类
<?php
//设置命名空间
namespace Admin\Model;
//引入model基类
use Think\Model;
//创建自定义基类
class GoodsModel extends Model{
}
?>
2、配置tp与数据库的连接信息
- 1、数据库配置项在tp的惯例配置文件/ThinkPHP/Conf/convention.php
以下配置信息是关于数据库的
/* 数据库设置 */
'DB_TYPE' => '', // 数据库类型
'DB_HOST' => '', // 服务器地址
'DB_NAME' => '', // 数据库名
'DB_USER' => '', // 用户名
'DB_PWD' => '', // 密码
'DB_PORT' => '', // 端口
'DB_PREFIX' => '', // 数据库表前缀
'DB_PARAMS' => array(), // 数据库连接参数
'DB_DEBUG' => TRUE, // 数据库调试模式 开启后可以记录SQL日志
'DB_FIELDS_CACHE' => true, // 启用字段缓存
'DB_CHARSET' => 'utf8', // 数据库编码默认采用utf8
'DB_DEPLOY_TYPE' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'DB_RW_SEPARATE' => false, // 数据库读写是否分离 主从式有效
'DB_MASTER_NUM' => 1, // 读写分离后 主服务器数量
'DB_SLAVE_NO' => '', // 指定从服务器序号
2、修改自己模块下的config文件
修改配置文件在/Application/Common/Conf/config.php的相应选项
<?php
return array(
//'配置项'=>'配置值'
/* 数据库设置 */
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => '127.0.0.1', // 服务器地址
'DB_NAME' => 'shop', // 数据库名
'DB_USER' => 'root', // 用户名
'DB_PWD' => '********', // 密码
'DB_PORT' => '3306', // 端口
'DB_PREFIX'=> 'shop_', // 数据库表前缀
);
3、具体数据信息如下
数据库名:shop
数据表名:shop_goods
表结构
3、实例化模型对象
- 1、常规的实例化方式
使用new关键字
Controller文件夹下IndexController.class.php文件
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化的过程中要使用命名命名空间
$model=new \Admin\Model\GoodsModel();
//dump是tp内置的一个函数。作用就是查看某一个变量的数据,等价于echo var_dump($model)
dump($model);
}
}
?>
- 2、使用tp内置的M函数实例化对象
一般使用在需要直接使用原生sql语句的时候
M函数有三个参数,可都传递或都不传递
第一个参数:指定具体的某一个数据表,默认没有前缀
第二个参数:指定具体的表前缀
第三个参数,指定具体的mysql连接信息
public function test2(){
//M函数有三个参数,可都传递或都不传递
//第一个参数:指定具体的某一个数据表,默认没有前缀
//第二个参数:指定具体的表前缀
//第三个参数,指定具体的mysql连接信息
$model=M();
dump($model);
}
- 3、使用tp内置的D函数实例化对象
使用D函数传递参数是,需要指定具体的自定义的模型的名称
D函数可以跨模块执行,只需要指定具体的参数就可以,参数为“模块名称/模型名称”
当实例化某一个不存在的自定义模型,就会使用tp的模型积累进行实例化操作
public function test3(){
$model=D('Goods');//参数是模型名称
dump($model);
}
- 4、D函数和M函数的区别
M永远实例化TP的模型的基类
D会优先实例化自定义的模型类,如果自定义模型类不存在就会实例化tp模型基类
建议使用D函数实例化模型类
4、模型的curd(增删改查)操作
add,add(all)
delete
save
find,select
5、add数据的写入
-
1、实例化模型对象
-
2、拼接具体要写入的数据
使用add数据写入,add是写入单条数据,所以需要使用一维数组格式(关联数组)。下标具体的字段名称
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//拼接具体要写入的数据使用数组
$data=array(
'goods_name'=>'test4',
'addtime'=>time(),
'goods_body'=>'test44'
);
//具体实现添加
$res=$model->add($data);
dump($res);
}
}
?>
6、addAll写入多条数据
创建一个二维数组,进行写入
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//写入多条数据则使用二维数组,第一位下标要从0开始
$data=array(
array('goods_name'=>'test5',
'addtime'=>time(),
'goods_body'=>'test55'),
array('goods_name'=>'test6',
'addtime'=>time(),
'goods_body'=>'test66')
);
//具体实现添加
$res=$model->addAll($data);
dump($res);
}
}
?>
7、save修改所有数据
- 1、首先需要一个模型对象
- 2、指定需要修改的内容
只需要需要修改内容的一维数组即可,需要指定条件进行更新
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//写入多条数据则使用二维数组,第一位下标要从0开始
$data=array(
'id'=>'2',//执行修改id为6的数据
'goods_name'=>'test666'
);
//具体实现添加
$res=$model->save($data);
dump($res);
}
}
?>
当需要判断是否更新成功,需要使用返回值与false进行全等判断,如果全等判断成立说明目前修改失败,因为save返回一个逻辑值
8、setField只更新个别字段
setField()实现更新具体某一些字段对应的内容
两种使用方式
- 1、第一种方法修改多个字段,直接个setField传递一个参数,需要一个一维数组,下标为字段名称,具体的值就是每一个字段对应要修改的内容
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//执行查询
$res=$model->where("id=3")->setField(array('goods_name'=>test999,'goods_body'=>'body666'));
dump($res);
}
}
?>
- 2、第二种方法修改单个字段,对第一个参数指定具体的某一个字段名称,第二个字段对应字段所需要修改的内容
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//执行查询
$res=$model->where("id=1")->setField('goods_name','tp999');
dump($res);
}
}
?>
9、setInc,setDec字段值增减操作
setInc:指定将某一个字段的值进行增加操作
setDec:指定将某一个字段的值进行减少操作
两个参数,
第一个参数是指定具体的字段名称
第二个参数指定增减的具体值,如果不指定则增减1
- 1、实例化模型对象
- 2、通过模型来操作修改
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//执行查询
$model->where("id=6")->setInc('addtime');
//第二个参数指定了减少的具体值
$model->where("id=4")->setDec('addtime',100);
}
}
?>
10、连贯操作(链式)修改操作中的where方法
当模型调用where方法,tp会根据where中的具体内容设置条件,返回具体的模型对象,再去调用save方法
where方法可以配合查询、删除等操作
对于where指定具体的条件使用方式比较多,经常使用的是数组格式来指定具体的条件,第二种方式是使用原生sql语句来指定
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//写入多条数据则使用二维数组,第一位下标要从0开始
$data=array(
'goods_name'=>'test88888'
);
//具体实现添加
$res=$model->where("goods_name='test4'")->save($data);
dump($res);
}
}
?>
11、单条数据查询-find
find:作用实现获取一条数据,返回的数据格式是一维数组
select:作用实现获取多条数据,返回的数据格式是二维数组
1、先获取模型对象
2、通过模型对象来执行查找
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//执行查询
$data=$model->where("id=6")->find();
dump($data);
}
}
?>
返回
array(5) {
[“id”] => string(1) “6”
[“goods_name”] => string(6) “test55”
[“goods_img”] => string(8) "default "
[“addtime”] => string(10) “1609226494”
[“goods_body”] => string(6) “test66”
}
12、多条数据查询-select
select:作用实现获取多条数据,返回的数据格式是二维数组
- 1、先获取模型对象
- 2、通过模型对象来执行查找
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//执行查询
$data=$model->where("goods_name='test5'")->select();
dump($data);
}
}
?>
结果:
array(2) {
[0] => array(5) {
[“id”] => string(1) “2”
[“goods_name”] => string(5) “test5”
[“goods_img”] => string(8) "default "
[“addtime”] => string(10) “1609226203”
[“goods_body”] => NULL
}
[1] => array(5) {
[“id”] => string(1) “6”
[“goods_name”] => string(5) “test5”
[“goods_img”] => string(8) "default "
[“addtime”] => string(10) “1609226494”
[“goods_body”] => string(6) “test66”
}
}
13、delete数据删除
- 1、先获取模型对象
- 2、通过模型对象来执行删除
使用delete进行删除非常危险,tp为了安全不会正常地执行删除操作
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//执行查询
$res=$model->where("id=5")->delete();
dump($res);
}
}
?>
PS:可以通过对象调用getlastSql()方法到最后所执行的sql语句
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//执行查询
$res=$model->where("id=5")->delete();
$str=$model->getLastSql();
echo $str;
dump($res);
}
}
?>
14、数据表字段的缓存
当直接使用$model->sage( $data)时必须要指定修改数据的主键才可以修改,tp为什么能知道具体哪一个字段是主键呢,因为:
每次实例化模型对象,tp都会分析对应数据表的字段信息,因此就可以知道具体哪一个才是主键字段
字段缓存就是将字段信息存储到某个文件中,下次实例化会直接读取文件的信息,不会再去分析具体的数据表的结果
15、开启字段缓存功能
- 1、关闭调试模式
define(‘APP_DEBUG’,false);
- 2、查看第一次访问的效果
- 3、再次访问
具体缓存文件在哪呢
Application\Runtime\Data\_fields\shop.shop_goods.php
16、数据表字段定义
在自定义的模型中将具体的字段信息保存到某一个具体的属性中(固定的属性名称)。本质也是将具体的字段信息保存到变量中。变量会载入到内存。对于内存的速度比磁盘的速度要更加快,因此使用字段定义功能比字段缓存效果更加高。
- 1、修改模型
·实现字段的定义,需要将每一个字段都写入到对应的数组中,每一个字段就是一个具体的元素
·注意每一个字段都需要写入进去,如果缺少某一个字段,在进行数据交互时,缺少的对应字段就不能正常的进行交互
<?php
//设置命名空间
namespace Admin\Model;
//引入model基类
use Think\Model;
//创建自定义基类
class GoodsModel extends Model{
//通过属性指定具体的主键字段信息
protected $pk='id';//默认为id,如果主键是id,则可以不写
//实现字段的定义,需要将每一个字段都写入到对应的数组中,每一个字段就是一个具体的元素
//注意每一个字段都需要写入进去,如果缺少某一个字段,在进行数据交互时,缺少的对应字段就不能正常的进行交互
protected $field=array('id','goods_name','goods_img','addtime','goods_body');
}
?>
17、数据创建
就是使用模型对象调用create方法来自动的接受提交的数据内容,并且对内容进行过滤操作(根据数据表的结构信息)
create的功能非常多,如自动验证等
- 1、修改商品的添加模板
Application\Admin\View\Goods\add.html
下面的pic图片地址命名故意命名错,为了将来使用字段映射,实际应该为goods_img
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
</head>
<body>
<form action="" method="post">
<div><label>商品名称</label><input name="goods_name" type="text"/></div>
<div><label>图片地址</label><input name="pic" type="text" value="http://www.mycodes.net"/></div>
<div><label>内容</label><textarea name="goods_body" cols="" rows=""></textarea></div>
<div><input name="" type="submit" value="提交"/></div>
</form>
</body>
</html>
页面效果
- 2、同时设置了Admin模块下的Goods控制器
可以根据不同的请求方式进行反应
IS_GET:判断当前请求是否是get方式。如果get,值为真
IS_POST:判断当前请求是否是post方式。如果post,值为真
IS_AJAX:判断当前请求是否是ajaxt方式。如果是ajax,值为真
<?php
namespace Admin\Controller;
use Think\Controller;
class GoodsController extends Controller{
public function test1(){
//需要add能够实现显示具体的表单及实现处理表单的提交
//可以根据不同的请求方式进行反应
if (IS_GET) {
$this->display('add');
}else{
//post表单的提交
//创建模型对象
$model=D("Goods");
$data=$model->create();
dump($data);
}
}
}
?>
这里由于pic不是数据库对应的字段自然地被过滤掉了
- 3、目录结构是
18、字段映射
为了在表单中隐藏真实字段名称,可以使用假名,但是为了确保使用假名后也能够使用数据的创建功能,可以在自定义的模型中通过某一个属性(有固定的名称)指定具体的假名与真名的对应关系。这就是字段映射。
- 1、修改模型编辑映射
实现字段的映射功能,对应的是数组格式(关联数组),在数组格式中体现出假名与真名的对应关系。
要求对每个元素的下标表示假名,具体的内容就是真实名称
Application\Admin\Model\GoodsModel.class.php
<?php
//设置命名空间
namespace Admin\Model;
//引入model基类
use Think\Model;
//创建自定义基类
class GoodsModel extends Model{
//实现字段的映射功能,对应的是数组格式,在数组格式中体现出假名与真名的对应关系
protected $_map=array(
'name'=>'goods_name',
'pic'=>'goods_img',
'body'=>'goods_body'
);
}
?>
- 2、修改模型增加属性(假名)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
</head>
<body>
<form action="" method="post">
<div><label>商品名称</label><input name="name" type="text"/></div>
<div><label>图片地址</label><input name="pic" type="text" value="http://www.mycodes.net"/></div>
<div><label>内容</label><textarea name="body" cols="" rows=""></textarea></div>
<div><input name="" type="submit" value="提交"/></div>
</form>
</body>
</html>
- 3、查看效果
array(3) {
[“goods_name”] => string(9) “张三丰”
[“goods_img”] => string(22) “http://www.mycodes.net”
[“goods_body”] => string(12) “武当奇侠”
}
19、自动验证
在使用create创建数据时自动对提交的具体内容进行合法性校验操作
数据校验有两种方式
1、静态方式:在模型类里面通过 $validate属性 定义验证规则
2、动态方式:使用模型类的validate方法动态创建自动验证规则。
无论什么方式,验证规则的定义的统一规则,定义格式为:
array(
array(验证字段1,验证规则,错误提示[验证条件,附加规则,验证时间]),
array(验证字段1,验证规则,错误提示[验证条件,附加规则,验证时间]),
)
验证字段:需要在表单验证的字段名称,可以是数据表中的字段名称,也可以使是表单中的辅助字段名称,如验证码(作为辅助字段)
验证规则:当附加规则指定使用哪一种方式方式进行验证,验证规则会在附加规则的基础上再次指定具体使用的规则,
·当使用附加规则为regex时,验证规则可以写上具体的正则表达式。
·当使用附加规则为function时,验证规则可以写上具体的函数名称(php内置函数名称、tp公共的函数名称,自定义的公共函数名称。)
·当附加规则为callback,验证规则可以协商具体当前模型类下的具体某一个方法的名称
错误提示:验证不通过时,给用户的提示语
验证条件:控制当前的验证规则是否执行,self::EXISTS_VALIDATE的取值为0,1,2
附加规则:指定当前的验证规则使用哪一种方式进行验证。
验证时间:控制当前的验证规则具体什么时间生效:
self:MODEL_INSERT或1:新增数据时验证
self:MODEL_UPDATE或2:编辑数据时验证
self:MODEL_BOTH或3:全部情况下验证
20、自动验证案例
- 1、修改商品添加模板
增加了商品价格输入框
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
</head>
<body>
<form action="" method="post">
<div><label>商品名称</label><input name="name" type="text"/></div>
<div><label>商品价格</label><input name="goods_price" type="text"/></div>
<div><label>图片地址</label><input name="pic" type="text" value="http://www.mycodes.net"/></div>
<div><label>内容</label><textarea name="body" cols="" rows=""></textarea></div>
<div><input name="" type="submit" value="提交"/></div>
</form>
</body>
</html>
- 2、修改商品模型(因为增加了商品价格字段)
<?php
//设置命名空间
namespace Admin\Model;
//引入model基类
use Think\Model;
//创建自定义基类
class GoodsModel extends Model{
//实现字段的映射功能,对应的是数组格式,在数组格式中体现出假名与真名的对应关系
protected $_map=array(
'name'=>'goods_name',
'pic'=>'goods_img',
'body'=>'goods_body'
);
//增加属性,指定具体的自动验证规则
protected $_validate=array(
array('goods_name','checkName','goods_name error',1,'callback',3),
array('goods_price','check_Price','goods_price error',1,'function',3),
array('goods_body','check_Price','goods_body error',1,'regex',3),
);
}
?>
- 3、修改商品模型在,增加验证方法
<?php
//设置命名空间
namespace Admin\Model;
//引入model基类
use Think\Model;
//创建自定义基类
class GoodsModel extends Model{
//实现字段的映射功能,对应的是数组格式,在数组格式中体现出假名与真名的对应关系
protected $_map=array(
'name'=>'goods_name',
'pic'=>'goods_img',
'body'=>'goods_body'
);
//增加属性,指定具体的自动验证规则
protected $_validate=array(
array('goods_name','check_Name','goods_name error',1,'callback',3),
array('goods_price','check_Price','goods_price error',1,'function',3),
array('goods_body','require','goods_body error',1,'regex',3),
);
//检查商品名称是否满足格式要求
public function check_Name($goods_name){
//根据商品名称的长度判断,大于3就不满足格式要求
if(mb_strlen($goods_name,'utf-8')>3){
return false;
}
return true;
}
}
?>
- 4、增加项目的公共函数
需要在Application\Common\Common\创建一个function.php
定义项目使用的公共函数,对于此文件下的函数会自动载入到项目
<?php
//定义项目使用的公共函数,对于此文件下的函数会自动载入到项目
//检查当前提交的商品价格是否满足格式要求
function check_Price($goods_price){
if($goods_price<=0){
return false;
}
return true;
}
?>
- 5、在入口文件中开启调试模式
- 6、修改控制器的test方法进行显示
<?php
namespace Admin\Controller;
use Think\Controller;
class GoodsController extends Controller{
public function test1(){
//需要add能够实现显示具体的表单及实现处理表单的提交
//可以根据不同的请求方式进行反应
if (IS_GET) {
$this->display('add');
}else{
//post表单的提交
//创建模型对象
$model=D("Goods");
$data=$model->create();
if(!$data){
//说明目前有数据格式不满足要求
//$model->getError能够获取具体的错误信息
dump($model->getError());
}
dump($data);
}
}
}
?>
最终
21、自动完成
在使用create创建数据是tp会自动对接受的内容进行增加或者修改的操作
自动完成的使用场景
- 1、部分字段在表单中没有体现出来(不需要用户进行录入操作,),但是对于这些字段在数据的添加或者是修改时,又需要将具体对应的内容写入到数据库中
- 2、使用create方法创建数据后,可能部分数据在格式上不满足要求,就需要将具体的内容转换格式之后再写入到数据库
自动完成的使用方式
- 1、静态方式:在模型类里通过 $_auto属性定义处理规则
- 2、动态方式:使用模型类的auto方法动态创建自动处理规则
array(
array(完成字段1,完成规则,[完成条件,附加规则]),
array(完成字段2,完成规则,[完成条件,附加规则]),
)
完成字段:
完成规则:
完成条件:
self:MODEL_INSERT或1:新增数据时验证
self:MODEL_UPDATE或2:编辑数据时验证
self:MODEL_BOTH或3:全部情况下验证
附加规则:主要是function和callback
22、自动完成案例
修改GoodsController.class.php文件
<?php
namespace Admin\Controller;
use Think\Controller;
class GoodsController extends Controller{
public function test1(){
//需要add能够实现显示具体的表单及实现处理表单的提交
//可以根据不同的请求方式进行反应
if (IS_GET) {
$this->display('add');
}else{
//post表单的提交
//创建模型对象
$model=D("Goods");
//使用动态方式完成表单,定义具体自动完成规则
$auto=array(
array('addtime','time',1,'function')
);
$data=$model->auto($auto)->create();
if(!$data){
//说明目前有数据格式不满足要求
//$model->getError能够获取具体的错误信息
dump($model->getError());
}
dump($data);
}
}
}
?>
添加数据时显示:
23、统计查询方法
- 1、查看统计查询的方法
Count:
Max:
Min:
Avg:
Sum:
24、统计查询方法-Count
1、创建一个控制器方法
修改呢Application\Admin\Controller\IndexController.class.php
<?php
namespace Admin\Controller;
use Think\Controller;
class IndexController extends Controller{
public function test1(){
//实例化模型对象
$model=D('Goods');
//计算当前数据的总行数
echo $model->count();
echo '<hr>';
//计算id中的最大值
echo $model->max('id');
echo '<hr>';
//计算所有数据id的总和
echo $model->sum('id');
echo '<hr>';
//使用where指定具体的条件进行统计查询
echo $model->where("goods_name='test999'")->sum('id');
$this->display(news);
}
}
?>
结果为:
25、开启tp开发者工具
修改Application\common\config\config.php
//开启tp的开发者工具
'SHOW_PAGE_TRACE'=>true,