连接数据库与模型初探
连接数据库
- ThinkPHP 采用内置抽象层将不同的数据库操作进行封装处理;
- 数据抽象层基于PDO模式,无须针对不同的数据库编写相应的代码;
- 使用数据库的第一步,就是连接你的数据库;
- 在根目录的
config
下的database.php
可以设置数据库连接信息; - 大部分系统已经给了默认值,你只需要修改和填写需要的值即可;
- 本地测试,会优先采用
.env
的配置信息,我们和database.php
配置对应上即可;
'type' => Env::get('database.type', 'mysql'),
'hostname' => Env::get('database.hostname', '127.0.0.1'),
'database' => Env::get('database.database', 'grade'),
'username' => Env::get('database.username', 'root'),
'password' => Env::get('database.password', '123456'),
'hostport' => Env::get('database.hostport', '3306'),
'charset' => Env::get('database.charset', 'utf8'),
'prefix' => Env::get('database.prefix', 'tp_'),
- 可以通过删除改变
.env
的配置,或删除.env
来验证database
的执行优先级; - 在
database.php
配置中,default
表示设置默认的数据库连接; connections
配置数据库连接信息,可以是多个数据库,便于切换;- 默认的数据库连接名称为:'mysql',再复制一组数据库链接信息:'demo'切换;
- 创建一个用于测试数据连接的控制器:
DataTest.php
;
<?php
namespace app\controller;
use think\facade\Db;
class Datatest
{
public function index()
{
$user = Db::table('tp_user')->select();
//$user = Db::connect('mysql')->table('tp_user')->select();
return $user;
return json($user);
}
public function demo()
{
$demo = Db::connect('demo')->table('tp_user')->select();
return json($demo);
}
}
- 暂时不必理解这里的代码,只要运行起来看到效果即可,后面章节会详解;
模型初探
- 在 app 目录下创建一个
model
目录,并创建User.php
的模型类; User
继承模型基类,即可实现数据调用,后面章节会详解讲解;- 而受保护的字段$connection,则是切换到
demo
数据库; - 需要引入
Model
类并继承该类; - 控制器端的调用方式如下,具体原理,后面模型章节会详解;
<?php
namespace app\model;
use think\Model;
class User extends Model
{
protected $connection = 'demo';
}
- 数据库新增demo库和user表
- 对应需要修改数据库配置和表前缀
- 修改
Datatest.php
,引入User
模型
调用getUser方法,访问的是demo库的user表
<?php
namespace app\controller;
use think\facade\Db;
use app\model\User;
class Datatest
{
public function index()
{
$user = Db::table('tp_user')->select();
//$user = Db::connect('mysql')->table('tp_user')->select();
return $user;
return json($user);
}
public function getUser()
{
$user = User::select();
return json($user);
}
}
数据库的数据查询
数据库查询必须引入Db类
#引入Db类
use think\facade\Db;
单数据查询
- Db::table()中 table 必须指定完整数据表(包括前缀);
- 如果希望只查询一条数据,可以使用
find()
方法,需指定where
条件,如果没有查询到默认返回null
;
Db::table('tp_user')->where('id', 27)->find();
- Db::getLastSql()方法,可以得到最近一条 SQL 查询的原生语句;
Db::getLastSql();
- 没有查询到任何值,则返回 null;
- 使用 findOrFail()方法同样可以查询一条数据,在没有数据时抛出一个异常;
Db::table('tp_user')->where('id', 1)->findOrFail();
- 使用 findOrEmpty()方法也可以查询一条数据,但在没有数据时返回一个空数组;
Db::table('tp_user')->where('id', 1)->findOrEmpty();
数据集查询
- 想要获取多列数据,可以使用
select()
方法;
Db::table('tp_user')->select();
// 执行的sql语句
// SELECT * FROM `tp_user`
- 多列数据在查询不到任何数据时返回空数组,使用
selectOrFail()
抛出异常;
Db::table('tp_user')->where('id', 1)->selectOrFail();
- 在 select()方法后再使用 toArray()方法,可以将数据集对象转化为数组;
Db::table('tp_user')->select()->toArray();
- 当在
database.php
配置文件中设置了前缀,那么我们可以使用name()
方法忽略前缀;
// database.php
// 'prefix' => env('database.prefix', 'tp_'),
Db::name('user')->select();
其它查询
- 通过
value()
方法,可以查询指定字段的值(单个),没有数据返回null
;
Db::name('user')->where('id', 27)->value('username');
- 通过
colunm()
方法,可以查询指定列的值(多个),没有数据返回空数组;
Db::name('user')->column('username');
- 可以指定
id
作为列值的索引;
Db::name('user')->column('username', 'id');
- 如果处理的数据量巨大,成百上千那种,一次性读取有可能会导致内存开销过大;
- 为了避免内存处理太多数据出错,可以使用 chunk()方法分批处理数据;
- 比如,每次只处理100条,处理完毕后,再读取100条继续处理,示例以2条为例;
Db::table('tp_user')->chunk(2, function($users) {
foreach ($users as $key => $user) {
dump($user);
}
echo 1;
});
- 可以利用游标查询功能,可以大幅度减少海量数据的内存开销,它利用了PHP生成器特性。每次查询只读一行,然后再读取时,自动定位到下一行继续读取;
- 关键字
yield
,php官网关于生成器相关解释官网地址
$cursor = Db::table('tp_user')->cursor();
foreach($cursor as $user){
dump($user);
}
数据库的链式查询
查询规则
- 前面课程中我们通过指向符号
->
多次连续调用方法称为:链式查询; - 当
Db::name('user')
时,返回查询对象(Query),即可连缀数据库对应的方法; - 而每次执行一个数据库查询方法时,比如
where()
,还将返回查询对象(Query); - 只要还是数据库对象,那么就可以一直使用指向符号进行链式查询;
- 再利用
find()
,select()
等方法返回数组(Array)或数据集对象(Colletion); - 而
find()
和select()
是结果查询方法(放在最后),并不是链式查询方法;
Db::name('user')->where('id', 27)->order('id', 'desc')->find();
- 除了查询方法可以使用链式连贯操作,CURD操作也可以使用(后续课程研究);
- 那么,有多少种类似
where()
的链式操作方法呢?打开手册瞄一下
更多查询
- 如果多次使用数据库查询,那么每次静态创建都会生成一个实例,造成浪费;
- 我们可以把对象实例保存下来,再进行反复调用即可;
$userQuery = Db::name('user');
$dataFind = $userQuery->where('id', 27)->find();
$dataSelect = $userQuery->select();
- 当同一个对象实例第二次查询后,会保留第一次查询的值;
$data1 = $userQuery->order('id', 'desc')->select();
$data2 = $userQuery->select();
- 使用 removeOption()方法,可以清理掉上一次查询保留的值;
$userQuery->removeOption('where')->select();
数据库的数据新增
单数据新增
- 使用
insert()
方法可以向数据表添加一条数据,更多的字段采用默认;
$data = [
'username' => '辉夜',
'password' => '123',
'gender' => '女',
'email' => 'huiye@163.com',
'price' => 90,
'details' => '123',
];
Db::name('user')->insert($data);
- 如果新增成功,
insert()
方法会返回操作的行数;
echo Db::name('user')->insert($data);
- 如果你添加一个不存在的字段数据,会抛出一个异常
Exception
; - 如果想强行新增抛弃不存在的字段数据,则使用
strick(false)
方法,忽略异常;
Db::name('user')->strict(false)->insert($data);
- 如果我们采用的数据库是 mysql,可以支持
replace
写入; insert
和replace
写入的区别,前者表示表中存在主键相同则报错,后者则修改;
Db::name('user')->replace()->insert($data);
echo Db::getLastSql();
- 使用
insertGetId()
方法,可以在新增成功后返回当前数据ID;
echo Db::name('user')->insertGetId($data);
批量数据新增
- 使用
insertAll()
方法,可以批量新增数据,但要保持数组结构一致;
$data = [
[
'username' => '辉夜',
'password' => '123',
'gender' => '女',
'email' => 'huiye@163.com',
'price' => 90,
'details' => '123'
],
[
'username' => '辉夜',
'password' => '123',
'gender' => '女',
'email' => 'huiye@163.com',
'price' => 90,
'details' => '123'
]
];
Db::name('user')->insertAll($data);
- 批量新增也支持
replace()
方法,添加后改变成replace into
;
Db::name('user')->replace()->insertAll($data);
save()新增
- save()方法是一个通用方法,可以自行判断是新增还是修改(更新)数据;
- save()方法判断是否为新增或修改的依据为,是否存在主键,不存在即新增;
Db::name('user')->save($data);
数据库的修改删除
数据修改
- 使用
update()
方法来修改数据,修改成功返回影响行数,没有修改返回 0;
$data = [
'username' => '李白'
];
echo Db::name('user')->where('id', 38)->update($data);
- 如果修改数据包含了主键信息,比如 id,那么可以省略掉 where 条件;
$data = [
'id' => 231,
'username' => '李白'
];
echo Db::name('user')->update($data);
- 如果想让一些字段修改时执行SQL函数操作,可以使用
exp()
方法实现;
Db::name('user')->where('id', 232)
->exp('email', 'UPPER(email)')
->update();
- 如果要自增/自减某个字段,可以使用
inc/dec
方法,并支持自定义步长;
Db::name('user')->where('id', 232)
->inc('price')
->dec('status', 2)
->update();
- 一个更加简单粗暴灵活的方式,使用
::raw()
方法实现 3,4 点的内容;
Db::name('user')->where('id', 232)
->update(['email' => Db::raw('UPPER(email)'),
'price' => Db::raw('price + 1'),
'status' => Db::raw('status - 2')]);
- 使用 save()方法进行修改数据,这里必须指定主键才能实现修改功能;
Db::name('user')->where('id', 232)->save(['username'=>'李黑']);
数据删除
- 极简删除可以根据主键直接删除,删除成功返回影响行数,否则0;
Db::name('user')->delete(51);
- 根据主键,还可以删除多条记录;
Db::name('user')->delete([48,49,50]);
- 正常情况下,通过
where()
方法来删除;
Db::name('user')->where('id', 47)->delete();
- 通过 true 参数删除数据表所有数据,我还没测试,大家自行测试下;
Db::name('user')->delete(true);
数据库的查询表达式
比较查询
- 查询表达式支持大部分常用的SQL语句,语法格式如下:
where('字段名','查询表达式','查询条件');
- 在查询数据进行筛选时,我们采用
where()
方法,比如id=80
;
Db::name('user')->where('id', 80)->find();
Db::name('user')->where('id','=',80)->find();
- 使用
<>
,>
,<
,>=
,<=
可以筛选出各种符合比较值的数据列表;
Db::name('user')->where('id','<>',80)->select();
区间查询
- 使用
like
表达式进行模糊查询;
Db::name('user')->where('email','like','xiao%')->select();
like
表达式还可以支持数组传递进行模糊查询;
Db::name('user')->where('email','like',['xiao%','wu%'], 'or')->select();
// SELECT * FROM `tp_user` WHERE (`email` LIKE 'xiao%' OR `email` LIKE 'wu%')
like
表达式具有两个快捷方式whereLike()
和whereNoLike()
;
Db::name('user')->whereLike('email','xiao%')->select();
Db::name('user')->whereNotLike('email','xiao%')->select();
between
表达式具有两个快捷方式whereBetween()
和whereNotBetween()
;
Db::name('user')->where('id','between','19,25')->select();
Db::name('user')->where('id','between',[19, 25])->select();
Db::name('user')->whereBetween('id','19,25')->select();
Db::name('user')->whereNotBetween('id','19,25')->select();
in
表达式具有两个快捷方式whereIn()
和whereNotIn()
;
Db::name('user')->where('id','in', '19,21,29')->select();
Db::name('user')->where('id','in', [19, 21, 29])->select();
Db::name('user')->whereIn('id','19,21,29')->select();
Db::name('user')->whereNotIn('id','19,21,29')->select();
null
表达式具有两个快捷方式whereNull()
和whereNotNull()
;
Db::name('user')->where('uid','null')->select();
Db::name('user')->where('uid','not null')->select();
Db::name('user')->whereNull('uid')->select();
Db::name('user')->whereNotNull('uid')->select();
EXP查询
- 使用
exp
可以自定义字段后的SQL语句;
Db::name('user')->where('id','exp','IN (19,21,25)')->select();
Db::name('user')->whereExp('id','IN (19,21,25)')->select();
最后一次更新于2020-08-08 16:36
0 条评论