数据库模型操作
数据库操作
数据库配置
配置文件路径:
application\database.php
,里面设置了应用的全局数据库配置信息
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'test',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => true,
];
查询构造器
可以更方便执行数据库操作,查询构造器基于PDO实现,对不同的数据库驱动都是统一的语法
<?php
namespace app\home\controller;
use think\Controller;
// 引入Db类 数据库操作的入口类
use think\Db;
class Index extends Controller
{
// 查询数据
public function index()
{
// 查询admin表的所有数据,注意table方法必须指定完整的数据表名
$UserData = Db::table('pre_user')->select();
// ThinkPHP提供调试函数,如果需要打印结果可以使用该函数
halt($UserData);
// 如果设置了数据表前缀参数的话,可以使用
Db::name('user')->select();
// 查询id为1的单条数据
Db::name('user')->where('id',1)->find();
// 查询status字段等于1的所有数据
Db::name('user')->where('status',1)->select();
// 查询某个字段的值
Db::name('user')->where('id',1)->value('name');
// 查询某一列的值
Db::name('user')->where('status',1)->column('name');
// 查询某一列的值并且指定索引
Db::name('user')->where('status',1)->column('name','id');
}
// 添加数据
public function add()
{
// insert方法
$data = ['foo' => 'bar', 'bar' => 'foo'];
Db::name('user')->insert($data);
// 返回自增主键 getLastInsID方法以及insertGetId方法
Db::name('user')->insert($data);
$userId = Db::name('user')->getLastInsID();
Db::name('user')->insertGetId($data);
// 添加多条数据
$data = [
['foo' => 'bar', 'bar' => 'foo'],
['foo' => 'bar1', 'bar' => 'foo1'],
['foo' => 'bar2', 'bar' => 'foo2']
];
Db::name('user')->insertAll($data);
}
// 编辑数据
public function edit()
{
// update => 更新数据 where => 条件 要注意的是更新数据必须要有条件
Db::name('user')->where('id', 1)->update(['name' => 'thinkphp']);
// 如果数据中包含主键,可以直接使用
Db::name('user')->update(['name' => 'thinkphp','id'=>1]);
}
// 删除数据
public function del()
{
// 根据主键删除
Db::name('user')->delete(1);
Db::name('user')->delete([1,2,3]);
// 条件删除
Db::name('user')->where('id',1)->delete();
Db::name('user')->where('id','<',10)->delete();
}
}
查询表达式
查询表达式支持大部分的SQL查询语法,也是
ThinkPHP
查询语言的精髓,查询表达式的使用格式
where('字段名','表达式','查询条件');
whereOr('字段名','表达式','查询条件');
表达式不分大小写,支持的查询表达式有下面几种,分别表示的含义是:
表达式 | 含义 |
---|---|
EQ、= | 等于(=) |
NEQ、<> | 不等于(<>) |
GT、> | 大于(>) |
EGT、>= | 大于等于(>=) |
LT、< | 小于(<) |
ELT、<= | 小于等于(<=) |
LIKE | 模糊查询 |
[NOT] BETWEEN | (不在)区间查询 |
[NOT] IN | (不在)IN 查询 |
[NOT] NULL | 查询字段是否(不)是NULL |
[NOT] EXISTS | EXISTS查询 |
EXP | 表达式查询,支持SQL语法 |
> time | 时间比较 |
< time | 时间比较 |
between time | 时间比较 |
notbetween time | 时间比较 |
<?php
namespace app\home\controller;
use think\Controller;
// 引入Db类 数据库操作的入口类
use think\Db;
class Index extends Controller
{
// 查询数据
public function index()
{
// 查询用户表id等于100的单条数据 下面的操作等效于where('id',100)
Db::name('user')->where('id','eq',100)->find();
Db::name('user')->where('id','=',100)->find();
// 查询用户表id不等于100的数据
Db::name('user')->where('id','neq',100)->select();
Db::name('user')->where('id','<>',100)->select();
// 模糊查询name带有thinkphp的数据
Db::name('user')->where('name','like','%thinkphp%')->select();
// 查询id在1到8区间的数据 同时支持数组的写法
Db::name('user')->where('id','between',[1,8])->select();
Db::name('user')->where(['id'=> ['between',[1,8]]])->select();
// 数组写法
Db::name('user')->where(['id'=> ['between',[1,8]],'status' => ['=',1]])->select();
// exp查询的条件不会被当成字符串,所以后面的查询条件可以使用任何SQL支持的语法,包括使用函数和字段名称
Db::name('user')->where('id','exp',' IN (1,3,8) ')->select();
}
}
链式操作
支持链式操作的查询方法包括
方法名 | 描述 |
---|---|
alias | 设置表别名 |
field | 查询字段 |
limit | 指定查询多条数据 |
order | 排序 |
group | 根据一个或多个列对结果集进行分组 |
join | 根据两个或多个表中的列之间的关系 |
fetchSql | 直接返回SQL而不是执行查询 |
<?php
namespace app\home\controller;
use think\Controller;
// 引入Db类 数据库操作的入口类
use think\Db;
class Index extends Controller
{
// 查询数据
public function index()
{
// 链表查询
// INNER JOIN: 等同于 JOIN(默认的JOIN类型),如果表中有至少一个匹配,则返回行
// LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
// RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
Db::table('think_user')
->alias('a')
->join('think_dept b ','b.user_id= a.id')
->select();
Db::table('think_user')
->alias('a')
->join('think_dept b ','b.user_id= a.id')
->select();
// 按照用户id进行分组统计
Db::table('user')
->field('user_id,username,max(score)')
->group('user_id')
->select();
// 查询5个满足条件的数据 并按照id倒序排列
Db::table('user')
->where('status', 1)
->field('id,name')
->order('id', 'desc')
->limit(5)
->select();
}
}
聚合查询
经常会用到一些统计数据,例如当前所有(或者满足某些条件)的用户数、所有用户的最大积分、用户的平均成绩等等
方法 | 说明 |
---|---|
count | 统计数量,参数是要统计的字段名(可选) |
max | 获取最大值,参数是要统计的字段名(必须) |
min | 获取最小值,参数是要统计的字段名(必须) |
avg | 获取平均值,参数是要统计的字段名(必须) |
sum | 获取总分,参数是要统计的字段名(必须) |
<?php
namespace app\home\controller;
use think\Controller;
// 引入Db类 数据库操作的入口类
use think\Db;
class Index extends Controller
{
public function index()
{
// 获取用户数
Db::table('think_user')->count();
// 获取用户的最大积分
Db::table('think_user')->max('score');
}
}
事务操作
最简单的方式是使用transaction方法操作数据库事务,当闭包中的代码发生异常会自动回滚
// 写入失败的话,系统会自动回滚,写入成功的话系统会自动提交当前事务
Db::transaction(function () {
Db::table('think_user')->find(1);
Db::table('think_user')->delete(1);
});
也可以手动控制事务
// 启动事务
Db::startTrans();
try {
Db::table('think_user')->find(1);
Db::table('think_user')->delete(1);
// 提交事务
Db::commit();
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
}
模型
模型类通常完成实际的业务逻辑和数据封装,并返回和格式无关的数据
定义模型
<?php
namespace app\common\model\Business;
// 引入TP基础模型
use think\Model;
// 引入软删除模型 对数据频繁使用删除操作会导致性能问题,软删除的作用就是把数据加上删除标记,而不是真正的删除,同时也便于需要的时候进行数据的恢复
use traits\model\SoftDelete;
// 继承TP基础模型 注意:模型会自动对应数据表,模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写
class Business extends Model
{
// 使用软删除模型
use SoftDelete;
// 设置当前模型对应的完整数据表名称(如果你的命名规则和上面的系统约定不符合时才需要设置该属性)
protected $table = 'pre_business';
// 开启自动写入时间戳字段 默认时间类型是int,如果是datetime的,那么需要把true改为datetime
protected $autoWriteTimestamp = true;
// 定义时间戳字段名 默认创建时间字段为create_time,更新时间字段为update_time
protected $createTime = 'createtime';
// 如果不需要更新时间把该属性设置为false
protected $updateTime = false;
// 定义软删除字段(标识符)
protected $deleteTime = 'deletetime';
// 追加数据表不存在的字段
protected $append = [
'gender_text'
];
/**
* 定义数据表中不存在的字段的获取器 以get不存在的字段名Attr该规则命名方法名(根据业务需求)
* @param $value 当前字段的值
* @param $data 当前的所有数据数组
*/
public function getGenderTextAttr($value,$data)
{
$gender = !empty($data['gender']) ? $data['gender'] : 0;
$genderList = [0 => '保密',1 => '男',2 => '女'];
return $genderList[$gender];
}
/**
* 定义数据表中存在的字段的获取器 以get字段名 (根据业务需求)
* @param $value 当前字段的值
*/
public function getDealAttr($value)
{
$dealList = [0 => '未成交',1 => '已成交'];
return $dealList[$value];
}
// 关联查询(根据业务需求)
public function address()
{
/*
belongsTo 相应关联查询
第一个参数 model => 需要关联模型
第二个参数 foreignKey => 外键
第三个参数 locaKey => 主键
第四个参数 alias => 模型别名
第五个参数 joinType => 链表查询(LEFT,INNER,RIGHT)
setEagerlyType 设置预载入方法
0 => JOIN查询
1 => IN查询
*/
return $this->belongsTo('app\common\model\Business\Address','busid','id',[],'LEFT')->setEagerlyType(0);
}
}
模型数据操作
跟
Db
类一样对数据库进行增删改查
<?php
namespace app\home\controller;
use think\Controller;
// 引入User模型
use app\common\model\User;
class Index extends Controller
{
// 定义属性
protected $UserModel = null;
// 控制器初始化
public function _initialize()
{
// 实例化模型再赋值给this 第一种写法
// $this->UserModel = new User();
// 第二种写法
$this->UserModel = model('User');
// 如果用助手调用多级模型 例如:路径:app\common\model\User\User
// $this->UserModel = model('User.User');
}
// 查询数据
public function index()
{
// 查询用户表的所有数据
$UserData = $this->UserModel->select();
// 查询用户表里的status为1的所有数据
$UserData = $this->UserModel->where(['status' => 1])->select();
// 查询单条数据 1 代表主键
$UserData = $this->UserModel->find(1);
$UserData = $this->UserModel->where(['name' => 'thinkPHP'])->find();
// 链式操作
$UserData = $this->UserModel->where(['status' => 1])->order('createtime DESC')->limit(10)->select();
}
// 添加数据
public function add()
{
// 第一种写法
$data = [
'username' => 'thinkPHP',
'status' => 1
];
$result = $this->UserModel->save($data);
// 第二种写法
$this->UserModel->username = 'demo';
$this->UserModel->status = 'normal';
$result = $this->UserModel->save();
// 获取自增ID
$userid = $this->UserModel->id;
// 批量新增
$data = [
['username'=>'thinkphp','email'=>'thinkphp@qq.com'],
['username'=>'onethink','email'=>'onethink@qq.com']
];
$result = $this->UserModel->saveAll($data);
}
// 编辑数据
public function edit()
{
// 需要修改的记录id
$userid = 6;
// 第一种写法 先查询再修改
$User = $this->UserModel->find($userid);
$User->nickname = 'onethink';
$User->mobile = 13023562356;
$result = $User->save();
// 第二种写法 如果更新数据里有主键就会作为更新条件
$data = [
'id' => $userid,
'nickname' => 'OneThink',
'mobile' => 13023568956
];
// isUpdate => 是否更新数据
$result = $this->UserModel->isUpdate(true)->save($data);
// 批量更新
$data = [
['id' => 5,'username'=>'ThinkPHP','email'=>'ThinkPHP@qq.com'],
['id' => 6,'username'=>'oneThink','email'=>'oneThink@qq.com']
];
$result = $this->UserModel->saveAll($data);
}
// 删除数据
public function del()
{
// 需要删除的记录id
$userid = 5;
// 第一种写法 先查询再删除
$User = $this->UserModel->find($userid);
$User->delete();
// 第二种写法 destroy => 支持数组 [1,2,3]
$result = $this->UserModel->destroy($userid);
}
}
软删除
在实际项目中,对数据频繁使用删除操作会导致性能问题,软删除的作用就是把数据加上删除标记,而不是真正的删除,同时也便于需要的时候进行数据的恢复
用法示例
首先在需要使用软删除的模型定义以下内容:
<?php
namespace app\common\model\Business;
// 引入TP基础模型
use think\Model;
// 引入软删除模型
use traits\model\SoftDelete;
// 继承TP基础模型
class Business extends Model
{
// 使用软删除模型
use SoftDelete;
// 设置数据表
protected $table = 'pre_business';
// 开启自动写入时间戳
protected $autoWriteTimestamp = true;
// 自定义创建时间字段
protected $createTime = 'createtime';
// 自定义更新时间字段
protected $updateTime = false;
// 定义软删除时间字段(标识符)
protected $deleteTime = 'deletetime';
}
然后在控制器调用
<?php
namespace app\home\controller;
use think\Controller;
class Index extends Controller
{
// 定义属性
protected $UserModel = null;
// 控制器初始化
public function _initialize()
{
// 实例化模型
$this->UserModel = model('User');
}
// 查询数据
public function index()
{
// 默认情况下查询的数据不包含软删除数据,如果需要包含软删除的数据,可以使用下面的方式查询
$data = $this->UserModel->withTrashed()->find();
$data = $this->UserModel->withTrashed()->select();
// 如果仅仅需要查询软删除的数据,可以使用
$data = $this->UserModel->onlyTrashed()->find();
$data = $this->UserModel->onlyTrashed()->select();
}
// 软删除操作
public function del()
{
// 需要删除的记录id
$userid = 5;
// 第一种写法 先查询再软删除
$User = $this->UserModel->find($userid);
$User->delete();
// 真实删除
$User->delete(true);
// 第二种写法 destroy => 支持数组 [1,2,3]
$result = $this->UserModel->destroy($userid);
// 真实删除
$result = $this->UserModel->destroy($userid,true);
}
}
验证器
ThinkPHP5.0验证使用独立的\think\Validate类或者验证器进行验证
定义验证器
路径:
app\common\validate
里面都是放验证器,如果validate
文件夹不存在的话,请手动创建
<?php
namespace app\common\validate\Business;
// 引入tp的验证器
use think\Validate;
// 客户验证器
class Business extends Validate
{
// 验证规则
protected $rule = [
/*
require => 字段必填
regex => 正则验证
unique => 验证字段值是否为唯一的 支持指定完整模型类 并且默认会优先检测模型类是否存在 不存在则检测数据表
*/
'mobile' => ['require','regex:/^1[3456789]{1}\d{9}$/','unique:business'],
'nickname' => ['require'],
'password' => ['require']
];
// 错误提示信息
protected $message = [
'mobile.require' => '手机号必填',
'mobile.regex' => '手机号格式错误',
'mobile.unique' => '手机号已注册',
'nickname.require' => '密码必填',
'password.require' => '密码必填',
];
// 验证场景
protected $scene = [
// 注册用户的验证场景
'add' => ['mobile','password'],
// 用户编辑资料的场景
'edit' => ['nickname']
];
}
点击该地址了解更多内置规则
用法示例
上面已经定义好验证器,接下来看验证器的用法
<?php
namespace app\home\controller;
use think\Controller;
class Index extends Controller
{
// 定义属性
protected $BusinessModel = null;
// 控制器初始化
public function _initialize()
{
// 实例化模型
$this->BusinessModel = model('Business.Business');
}
// 添加数据
public function add()
{
// 需要添加数据
$data = [
'mobile' => 13800000000,
'password' => 123456
];
// 第一种写法 控制器验证 需要继承TP基础控制器
$Validate = $this->validate($data,'common/Business/Business');
// 需要验证场景
$Validate = $this->validate($data,'common/Business/Business.add');
if($Validate === FALSE)
{
// 提示错误信息
$this->error($Validate);
}
$result = $this->BusinessModel->save($data);
// 第二种写法 模型验证
$result = $this->BusinessModel->validate('common/Business/Business')->save();
// 验证场景
$result = $this->BusinessModel->validate('common/Business/Business.add')->save($data);
if($result === FALSE)
{
// getError => 返回模型的错误信息
$this->error($this->BusinessModel->getError());
}
}
}