ThinkPHP5.0教程学习06:TP5 数据库与模型操作
学习教程来源于:
php中文网 ThinkPHP5 视频教程
ThinkPHP5.0完全开发手册
连接器与查询构造器
TP5采用的是惰性连接,故而仅在查询时才会连接到数据库
TP5的数据库操作对底层进行优化设计,对各种操作进行高级封装。既可以直接使用连接器进行高效的原生查询,也可以使用封装好的查询构造器进行直观便捷的查询,为模型操作打下基础。
创建数据库连接(静态与动态方式)
静态连接:应用/模块中的数据库配置文件database.php
动态连接:入口类Db.php
中的connect
(参数:数组/字符串)方法
参数名 | 默认值 | 说明 |
---|---|---|
type | mysql | 数据库类型 |
hostname | 127.0.0.1 | 服务器地址 |
database | 无 | 数据库名称 |
username | 无 | 数据库用户名 |
passward | 无 | 数据库密码 |
hostport | 3306 | 数据库连接端口 |
charset | utf8 | 数据库默认编码 |
prefix | 无 | 数据库表的前缀 |
debug | TRUE | 数据库调试模式 |
①动态设置
public function demo()
{$config = ['type' => 'mysql','hostname' => 'localhost','username' => 'root','password' => 'root','database' =>'tp5',];//1.获取数据库的链接实例/对象$link = Db::connect($config);//2.用连接实例调用查询类的查询方法$result = $link->table('staff')->select();//3.输出查询结果dump($result);
}
②动态配置连接字符串
mysql://root:1234@localhost:3306/thinkphp#usf8
数据库类型://用户名:密码@数据库地址:数据库端口/数据库名称#字符集
public function demo()
{//1.获取数据库的链接实例/对象 $config = 'mysql://root:root@localhost:3306/tp5#utf8';$link = Db::connect($config);//2.用连接实例调用查询类的查询方法$result = $link->table('staff')->select();//3.输出查询结果dump($result);
}
简化代码如下:
public function demo()
{$result = Db::table('staff')->select();dump($result);
}
!!!db()助手函数不支持惰性连接
数据库的原生查询实现原理:query和execute方法
Connection类:
①query(sql语句字符串,[参数绑定]):读操作—>select
②execute(sql语句字符串,[参数绑定]):写操作—>insert/update/delete
支持在原生查询的时候使用参数绑定,包括问号占位符或者命名占位符,参数绑定可以防止sql注入:
Db::query("select * from think_user where id=? AND status=?",[8,1]);
// 命名绑定
Db::execute("update think_user set name=:name where status=:status",['name'=>'thinkphp','status'=>1]);
Connection类实例通过入口类Db静态自动调用,不用显示写出
public function demo()
{//1.查询操作:查询工资大于4000远的员工信息用命名占位符进行参数绑定$sql = "select name,salary,dept from staff where salary > :salary";$result = Db::query($sql,['salary'=>4000]);//数组中的第一个元素和第一个问号对应dump($result);//2.更新操作:将Id=3的记录,salary增加1000$sql = "update staff set salary = salary+1000 where id=:id";$result = Db::execute($sql,['id'=>3]);dump($result);//返回受影响非记录条数//3.插入操作:默认添加到表的尾部的$sql = "insert into staff (name,sex,salary) values (:name,:sex,:salary)";$result = Db::execute($sql,['name'=>'郭襄','sex'=>0,'salary'=>3500]);dump($result);//4.删除操作:id=4的记录删除$sql = "delete from staff where id=:id";$result = Db::execute($sql,['id'=>4]);dump($result);}
查询构造器(抽象访问层)
①链式操作的功能是快速生成查询条件
②链式操作中的所有的方法都来自于query查询类
③链式操作的返回值就是当前的查询对象
生成查询条件的三种方法:表达式/数组/闭包(推荐)
2个方法:
①where():AND条件
②whereOr():OR条件
三种格式:
①where(‘字段名’,‘表达式’,‘查询条件’)
public function index()
{dump(Db::table('staff')->field(['name','salary'])->where('id','>',2)->select());
}
②where([‘字段名’=>[‘表达式’,‘查询条件’],…])
public function index()
{dump(Db::table('staff')->field(['name','salary'])->where(['id'=>['>',2],'salary'=>['>',3000]])->select());
}
③where(function($query){//链式查询语句;})
推荐方式:闭包的好处在于可以实现复杂的条件调用,且可以使用外部传入的变量
public function index(){dump(Db::table('staff')->field(['name','salary'])->where(function ($query){$query->where('id','>',1)->where('salary','>',4000);})->select());}
public function index(){$salary = 4000;// dump(// Db::table('staff')// ->field(['name','salary'])// ->where(function ($query) use ($salary){// $query->where('id','>',1)// ->where('salary','>',$salary);// })// ->select()// );dump(Db::select(function ($query) use ($salary) {$query->table('staff')->field(['name','salary'])->where(['id'=>['>',2],'salary'=>['>',$salary]]);}));}
select与find
参考:TP5 完全开发手册
查询一个数据使用find
:
// table方法必须指定完整的数据表名
Db::table('think_user')->where('id',1)->find();
find 方法查询结果不存在,返回 null
查询数据集使用select
:
Db::table('think_user')->where('status',1)->select();
select 方法查询结果不存在,返回空数组
数据库的新增与更新操作
1.新增
insert(['字段'=>'值'])
插入单条记录
insertAll(['二维数组'])
同时插入多条记录
2.更新
update(['字段'=>'值'])
根据条件更新一条或多条记录
setInc/setDec('字段','步长')
如果字段类型是数字型,且每次更新时有规律的,则可以使用这种方式
延迟更新
setInc/setDec
支持延时更新,如果需要延时更新则传入第三个参数
下例中延时10秒,给score字段增加1
Db::table('think_user')->where('id', 1)->setInc('score', 1, 10);
setInc/setDec
方法返回影响数据的条数
3.读取
find(主键)
单条读取,以一维数组的形式返回
select(主键)
返回多条满足条件的记录,可以以二维数组的方式返回
4.删除
delete(主键)
根据条件进行删除
delete(true)
无条件删除,清空数据表(危险操作)
delete删除方法不支持闭包
数据库的查询与删除操作:find/select/value/column/delete
1.value
获取某个字段的值
public function index()
{//value('字段','默认值')$result = Db::table('staff')->where('id',1)->value('name');dump($result);
}
2.column
输出一列数据
public function index()
{//value('字段','默认值')$result = Db::table('staff')->where('id','>',1)->column('name','id');//column的第一个参数为值,第二个参数为键名dump($result);
}
3.delete
删除数据
public function index()
{//value('字段','默认值')$result = Db::table('staff')->delete(7);return $result?'成功删除了'.$result.'条记录' : '删除失败';
}
模型的基本概念与基类Model介绍
模型是对实体的抽象描述,快速直观的展示出实体的特征。
TP5中的模型是指数据表(粗略理解)。
模型类中的属性与方法:
1.模型类中的属性和方法需要在基类Model中查看
2.Model.php类位于public/library/think/Model.php
3.该类是一个抽象类,不能被实例化,必须由子类继承并实现内部的全部抽象方法
模型的创建与使用:实例化与静态创建
模型与数据表的对应关系:
模型的属性与数据表的字段一一对应,数据表中的一行信息对应模型的一个实例。而模型的方法则定义了对当前数据表的一些操作。
①区别于联系
区别:
1.分工不同:Db类负责数据表的访问,模型专注于业务逻辑的处理
2.返回值不同:Db访问返回数组,模型操作返回对象
联系:
模型最终仍需调用Db类完成数据表的查询操作。
模型可以看做是一种更高级别的抽象,最终的底层仍然需要依靠Db类完成数据表的增删改查操作。
②创建模型
1.手工创建:
在应用或模块下创建模型目录model,并在该目录下创建与数据表同名的类文件:如User.php对应user.dbf表。(首字母大写)
2.命令创建:
在当前项目目录下,用命令:php think make:model 模块名/模型名
,会自动创建指定位置和命名空间的空模型,并自动与数据表绑定;
3.模型创建完成后,会自动获取当前数据表名称$table
,表中所有字段信息$field
,主键$pk
和数据库配置信息$connection
.同时会自动继承基类Model中所有属性和方法,protected类型在本模型中使用,public类型还可以在控制器使用,静态方法大多直接用在控制器,进行CURD操作。
③控制器中调用模型
一、实例化调用:
1.用new生成模型对象
2.用模型对象处理相关业务
<?php
namespace app\index\controller;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//1.实例化创建模型对象$staff = new Staff();$result = $staff -> where('id',3)->find();dump($result->getData('name'));}
}
二、静态调用:
1.通过静态查询直接将一个空模型转为数据模型
2.再调用相关方法完成增删改查操作
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//2.静态创建模型对象dump(Staff::get(3)->getData('sex'));}}
三、不推荐使用助手函数model()和添加模型类后缀
④模型数据访问方式
1.控制器访问(外部)->用模型对象:$model
2.模型访问(内部)->用伪对象变量:$this
模型的CURD操作
Cread/Update/Read/Delete
1.模型向数据表中添加数据:save()/saveAll()/update()
方法 | 说明 | 调用方法 | 返回值 |
---|---|---|---|
save($data=[])
|
添加单条 | 实例化 | 影响记录数 |
saveAll($data=[])
|
批量添加 | 实例化 | 模型对象数组 |
create($data=[])
|
单条添加 | 静态 | 模型对象 |
①数据创建过程可以触发很多操作,非Db类操作可比
②静态调用的实质其实仍是实例化调用,只是将CURD方法进行静态封装
③saveAll()
方法实际上是通过多次执行insert语句完成,很少用到
④理论上讲,通过模型向表中添加数据,尽可能都采用静态方式
<?php
namespace app\index\controller;
use think\Db;//导入数据库类
use app\index\model\Staff;//导入模型的命名空间class Index extends \think\Controller
{public function index(){//1.实例化模型,创建模型对象$staff = new Staff();//2.创建数据,采用的对象方式$staff->name = '韦小宝';$staff->sex = 1;$staff->salary = 9000;//3.执行数据添加操作$result = $staff->save();return $result ? '成功添加了'.$result.'条记录' : '添加失败';}
}
<?php
namespace app\index\controller;
use think\Db;//导入数据库类
use app\index\model\Staff;//导入模型的命名空间class Index extends \think\Controller
{public function index(){//1.实例化模型,创建模型对象$staff = new Staff();//2.创建数据,采用的对象方式$data = [['name'=>'陈近南','salary'=>40000],['name'=>'吴三桂','salary'=>60000],['name'=>'陈圆圆','salary'=>8000],];//3.执行数据添加操作$result = $staff->saveAll($data);dump($result);}
}
<?php
namespace app\index\controller;
use think\Db;//导入数据库类
use app\index\model\Staff;//导入模型的命名空间class Index extends \think\Controller
{public function index(){$result = Staff::create(['name'=>'林平之','sex'=>'1','salary'=>300]);dump($result->getData());}}
2.模型的更新操作:save()/saveAll()/update()
方法 | 说明 | 调用方法 | 返回值 |
---|---|---|---|
save($data=[],$where=[])
|
单条更新 | 实例化 | 影响记录数 |
saveAll($data=[].true )
|
批量更新 | 实例化 | 模型对象数组 |
update($data=[],$where=[],$field=[])
|
单条更新 | 静态 | 模型对象 |
1.不允许无条件更新,必须设置更新条件
2.可以将更新条件,如主键写在更新数据中,方法可以自动识别
3.更新条件可以使用闭包,完成更复杂的业务逻辑
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){$staff = new Staff();$data = ['Id'=>8,'name'=>'岳不群','sex'=>1];$staff->isUpdate(true)->save($data);dump($staff->getData());}
}
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){$staff = new Staff();$data = ['name'=>'张无忌','sex'=>1,];$where = ['Id'=>13,];$staff->save($data,$where);dump($staff->getData());}
}
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){$staff = new Staff();$data = [['Id'=>14,'name'=>'张无忌','sex'=>1],['Id'=>15,'name'=>'赵敏','sex'=>0],['Id'=>16,'name'=>'小昭','sex'=>1],];$staff->isUpdate(true)->saveAll($data);dump($staff->getData());}
}
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//update(更新数据,更新条件,允许更新的字段)$data = ['name'=>'韦一笑','sex'=>1,'salary'=>5600];$where = ['id'=>24];$field = ['name','sex'];$result = Staff::update($data,$where,$field);dump($result->getData());}
}
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//update(更新数据,更新条件,允许更新的字段)$data = ['name'=>'韦一笑','sex'=>1,'salary'=>5600];//更新条件使用闭包写法//闭包支持外部传入的变量$where = function ($query){$query->where('Id',25);};$field = ['name','sex'];$result = Staff::update($data,$where,$field);dump($result->getData());}
}
3.模型的查询操作:find()/select()/get()/all()
ORM模型(对象关系映射)
方法 | 调用方式 | 返回值 |
---|---|---|
find($where) 和get($where)
|
实例化/静态 | 模型对象 |
select($where) 和all($where)
|
实例化/静态 | 模型对象数组 |
1.原则来说,查询都应该采用静态查询方法
2.尽可能采用get()
和all()
方法代替find()
和selec()
3.牢记一条原则:一个模型对象实例应该唯一对应数据表的一条记录
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//模型实例化方式调用find()和get()方法//find和get方法都只返回满足条件的第一条记录$staff = new Staff;$where = function ($query){$query -> field(['name','salary'])-> where('id','=',3);};$result = $staff->find($where);//$result = $staff->get($where);dump($result->getData());}
}
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//模型实例化方式调用select()和all()方法$staff = new Staff;$where = function ($query){$query -> field(['name','salary'])-> where('salary','>',10000);};$result = $staff->select($where);//$result = $staff->all($where);foreach ($result as $value) {dump($value->getData());}}
}
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//模型实例化方式调用select()和all()方法$staff = new Staff;$where = function ($query){$query -> field(['name','salary'])-> where('salary','>',10000);};$result = $staff->all($where);foreach ($result as $key => $value) {// dump($value->getData());echo '记录编号:'.($key+1).' | 姓名:'.$value->name.' | 工资:'.$value->salary.'<br/>';}}
}
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//用模型类静态调用find和get方法$where = function ($query){$query->field(['name','salary'])->where('id','=',2);};// $result = Staff::find($where);$result = Staff::get($where);dump($result->getData());}
}
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){//用模型类静态调用select和all方法$where = function ($query){$query->field(['name','salary'])->where('id','>',2);};// $result = Staff::select($where);$result = Staff::all($where);foreach ($result as $value) {dump($value->getData());}}
}
4.模型的删除操作:delete()和destroy()
方法 | 调用方式 | 返回值 |
---|---|---|
delete() | 实例化 | 受影响的记录数量 |
destroy(条件/闭包) | 静态 | 受影响记录数量 |
1.delete()
不要传任何参数,他只删除当前模型对象对应的记录
2.destroy()
中的删除条件,推荐采用闭包方式
3.推荐用软删除替代该方法,即用更新的方式来实现删除操作
<?php
namespace app\index\controller;
use think\Db;
use app\index\model\Staff;class Index extends \think\Controller
{public function index(){$where = function ($query){$query->where('id','>',12)->where('sex','=',1)->whereOr('salary','>',4000);};$value = Staff::destroy($where);dump($value);}
}
5.模型读取器与修改器:getAttr()和setAttr()
①模型的读取器
触发条件:当用模型对象读取表中字段值的时候
应用场景:日期时间字段、集合或枚举数据、数字状态与文本转换、字段拼接
设置位置:在模型中设置,访问属性通常为protected,不允许外部直接访问
方法名称:get属性名称Attr($name,$data=[])
get FieldName Attr($name,$data=[])
驼峰命名法,对应表中字段:field_name
模型的读取器工作原理图
②模型的修改器
触发条件:当用模型对象向数据表中新增记录或更新字段值的时候
应用场景:日期时间字段、集合或枚举数据、数字状态与文本转换、字段拼接
设置位置:在模型中设置,访问属性通常为protected,不允许外部直接访问
方法名称:set属性名称Attr($name,$data=[])
set FieldName Attr($name)
驼峰命名法,对应表中字段:field_name
模型的修改器工作原理图
<?php
namespace app\index\model;
use think\Model;class Staff extends Model
{//$data中保存的是当前面模型的所有数据protected function getHireDateAttr($hiredate,$data){return $data['name'].'的入职时间是:'.date('Y-m-d',$hiredate);}protected function setHireDateAttr($hiredate){return strtotime($hiredate);}
}
?>
6.模型数据类型转换:$type
属性设置技巧
字符串类型是默认的读取类型
<?php
protected $type = ['name' => 'array', //以json格式写入,取出自动编码为array'age' => 'integer', //该字段写入和输出的时候都会字段转换为整型'salary' => 'float', //该字段写入和输出的时候都会自动转换为浮点型'dept' => 'serialize', //自动序列化写入,读取的时候自动反序列化'home' => 'json', //json_encode写入,读取时json_decode处理'hiredate' => 'timestamp', //用strtotime转为时间戳写入,读出按$dateFormat格式输出'birthday' => 'datetime' //读写都是按$dateFormat格式处理
];
?>
7.模型自动完成设置:$insert/$update/$auto
属性配置技巧
一、自动时间戳
1.模型中开启:protected $autoEriteTimestamp=true
2.在表中手工创建二个字段:create_time,update_time
3.用户自行新增和更新操作时,会自动将新增与更新时间写入表中
4.默认以时间戳格式写入,可以配置为:datatime格式
二、自动完成
1.$insert=['字段'=>'值',...];
//新增时自动插入到表中的
2.$update=['字段'=>'值',...];
//更新时自动更新字段值
3.$auto=['字段'=>'值',...];
//新增或更新时自动填入或更新字段值
通常要与类型自动转换属性:$type=['字段'=>'类型',...]
相配合
<?php
namespace app\index\model;
use think\Model;class Staff extends Model
{// 是否需要自动写入时间戳 如果设置为字符串 则表示时间字段的类型protected $autoWriteTimestamp=true;// 创建时间字段protected $createTime = 'create_time';// 更新时间字段protected $updateTime = 'update_time';// 保存自动完成列表protected $auto = ['salary'=>4500,'hiredate'=>'2019-09-16',];// 新增自动完成列表protected $insert = [// 'sex'=>1,'dept', //部门名称,根据员工性别sex字段的值确定'hiredate'=>'2019-09-16',];// 更新自动完成列表protected $update = ['dept'=>'测试部',];protected $type = ['hiredate'=>'timestamp',];protected function setDeptAttr($dept,$data){if ($data['sex']) {return $this->dept = '开发部';}else{return $this->dept = '客服部';}}
}
?>
ThinkPHP5.0教程学习06:TP5 数据库与模型操作相关推荐
- php环境搭建sqlserver,ThinkPHP5.0/5.1对接SQLServer数据库(宝塔环境)
SQLServer实际上是mssql,想要使用thinkphp的Db对象操作数据库前必须要在服务器上安装对应的扩展. 宝塔面板的PHP安装路径为/www/server/php/ 且支持多个PHP版本共 ...
- 【opencv4.3.0教程】06之基础结构3之Scalar_结构详解
目录 一.前言 二.温故知新--Rect_ 1.定义与成员变量 2.构造函数 3.常用方法 三.Scalar_ 1.定义 1.构造函数 2.基本操作 3.使用时的数据类型 2.常用方法 1.加法及加赋 ...
- think PHP5.0小程序,微信小程序ofo小黄车+thinkphp5.0打造全栈应用
链接 简介 本项目是采用PHP语言,THINKPHP5.0框架开发的全栈应用系统.在开发这个项目时,微信还没有OFO微信小程序,又不想下载APP去使用,只能在支付宝上面使用OFO,偶然间发现某人写了一 ...
- mysql数据库python基础知识_python学习之Mysql数据库编程基础知识介绍
在Python网络爬虫中,通常是通过TXT纯文本方式存储,其实也是可以存储在数据库中的:同时在WAMP(Windows.Apache.MySQL.PHP或Python)开发网站中,也可以通过Pytho ...
- php开源微商系统,Thinkphp5.0开发的一款新微商新零售系统整站源码(带安装教程)...
[温馨提示]源码包解压密码:www.youhutong.com 资源描述 Thinkphp5.0开发的一款新微商新零售系统整站源码 源码介绍: 这是一款thinkphp开发的新零售的派单工具平台 平台 ...
- SQL数据库教程-学习笔记2
SQL数据库教程-学习笔记2 文章目录 SQL数据库教程-学习笔记2 三.DML语言的学习 1.插入语句:insert into 2.修改语句:update 3.删除语句:delete 4.练习题 四 ...
- Fabric2.0部署学习进阶教程系列博文
Fabric2.0部署学习系列文章目录 1.<在本机上安装VMWare详细图文过程> https://blog.csdn.net/weixin_44750512/article/detai ...
- Yii Framework2.0开发教程(5)数据库mysql性能
继续<Yii Framework2.0开发教程(3)数据库mysql入门> 首先给予一定的尊重yii2数据库支持引进 Yii 基于 PHP's PDO一个成熟的数据库访问层的建立.它提供了 ...
- php 5.0打印数据库,thinkphp5.0数据库操作
ThinkPHP数据库处理: 1.MySQL的数据库连接 首先配置database.php文件 使用{dump(config('database));}来查看数据库的配置项 使用 {$res = Db ...
最新文章
- mysql5.5设置字符编码
- 《Android虚拟机》----虚拟机概述
- 字符串处理(POJ1782)
- Building Seam 2.0 Application with NetBeans 6.1
- c++中友元函数详解
- 剖析数组名、函数名(不是指针常量,更不是指针)
- TortoiseSVN版本管理的注意点
- android 软件测试文档,Android软件测试文档规范【参考】.doc
- 高校学生学籍系统C++amp;mysql
- 在freemarker文件中,html标签获取后台的值
- C#播放流媒体的几种方法
- mysql数据库的使用与理解( 基于ubuntu 14.0.4 LTS 64位)
- R语言基于mgcv包进行广义可加模型及交互作用演示(2)
- 如何制作微信抖音小游戏
- 梦想CAD软件(控件)图层介绍
- ae批量修改字体_AE脚本-批量文字替换图层样式属性编辑脚本Aescripts pt_TextEdit 2.41 + 使用教程...
- SourceInsight 软件乱码问题
- Moho Pro - Mac 上一款专业的二维动画制作软件,强大的功能让你尽情发挥创意
- 《茶馆》再开张 这出戏濮存昕、冯远征演了20年
- 无法部署应用目录 [D:\Tomcat\apache-tomcat-9.0.44\webapps\ROOT]java.lang.IllegalStateException: 启动子级时出错
热门文章
- C语言单引号和双引号
- 一个月体验,终于懂了程序员为什么喜欢用MacBook!
- 【计算机网络——制作双绞线】
- DAEMON Tools Lite 虚拟光驱,安装iso文件,提示需要管理员权限的问题解决
- 忽然看到自己十年前发的关于转计算机专业的帖子
- python爬取b站搜索结果_Python爬虫实例:爬取猫眼电影——破解字体反爬,Python爬虫实例:爬取B站《工作细胞》短评——异步加载信息的爬取,Python爬虫实例:爬取豆瓣Top250...
- Android 如何访问网络
- 计算机二级c语言编译,全国计算机等级考试教程-二级C语言.pdf
- vue里使用quill
- 新玺配资:外围市场大跌 A股很难不受影响