首页 » PHP » 正文

thinkphp5学习笔记(4)

数据库

5.0 的数据查询由低到高分三个层次,本章会涉及到前面两个:
1. 数据库原生查询(SQL查询);
2. 数据库链式查询(查询构造器);
3. 模型的对象化查询;

在第一章已经提到,在使用 Db 类进行数据库查询之前,首先必须先创建一个控制器类,以及一个操作方法
用于测试,类似于:

<?php
namespace app\index\controller;
use think\Db;
class Index
{
public function index()
{
// 后面的数据库查询代码都放在这个位置
}
}

数据库配置

我们给应用定义数据库配置文件( appliation/database.php ),里面设置了应用的全局数据库配置信息。

return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'test',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => true,
];

如果你使用了多个模块,并且不同的模块采用不同的数据库连接,那么可以在每个模块的目录下面单独定义
数据库配置。
后面的例子,我们都采用 index 模块的数据库配置文件( application/index/database.php ),配
置如下(模块数据库配置中我们使用了长连接):

return [
// 数据库名
'database' => 'demo',
// 数据库表前缀
'prefix' => 'think_',
// 数据库连接参数
'params' => [
// 使用长连接
\PDO::ATTR_PERSISTENT => true,
],
];
模块的数据库配置文件中只需要配置和全局数据库配置文件差异的部分,相同的不需要重复配置。

也可以在调用 Db 类的时候,使用 connect 方法动态连接或者切换不同的数据库,这个我们会在后面提到。

原生查询

设置好数据库连接信息后,我们就可以直接进行原生的SQL查询操作了,包括 query 和 execute 两个方法,分别用于查询和写入,下面我们来实现数据表 think_user 的CURD操作。

创建(create)

// 插入记录
$result = Db::execute('insert into think_data (id, name ,status) values (5, "thinkphp",1)');
dump($result);

更新(update)

// 更新记录
$result = Db::execute('update think_data set name = "framework" where id = 5 ');
dump($result);

读取(read)

// 查询数据
$result = Db::query('select * from think_data where id = 5');
dump($result);

query方法返回的结果是一个数据集(数组),如果没有查询到数据则返回空数组。
删除(delete)

// 删除数据
$result = Db::execute('delete from think_data where id = 5 ');
dump($result);

其它操作
可以执行一些其他的数据库操作,原则上,读操作都使用 query 方法,写操作使用 execute 方法即可,例
如:

// 显示数据库列表
$result = Db::query('show tables from demo');
dump($result);
// 清空数据表
$result = Db::execute('TRUNCATE table think_data');
dump($result);
query 方法用于查询,默认情况下返回的是数据集(二维数组), execute 方法的返回值是影响的行数。

切换数据库

在进行数据库查询的时候,支持切换数据库进行查询,例如:

$result = Db::connect([
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'thinkphp',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '123456',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'think_',
])->query('select * from think_data');
dump($result);

或者采用字符串方式定义(字符串方式无法定义数据表前缀和连接参数),如下:

$result = Db::connect('mysql://root:123456@127.0.0.1:3306/thinkphp#utf8')->query('selec
t * from think_data where id = 1');
dump($result);

为了简化代码,通常的做法是事先在配置文件中定义好多个数据库的连接配置,例如,我们在应用配置文件
( application/config.php )中添加配置如下:

// 数据库配置1
'db1' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'thinkphp',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '123456',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'think_',
],
// 数据库配置2
'db2' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'test',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'test_',
],

然后就可以直接在 connect 方法中传入配置参数进行切换数据库连接,例如:

$result = Db::connect('db1')->query('select * from think_data where id = 1');
$result = Db::connect('db2')->query('select * from think_data where id = 1');

connect 方法中的配置参数需要完整定义,并且仅仅对当此查询有效,下次调用 Db 类的时候还是使用默
认的数据库连接。如果需要多次切换数据库查询,可以使用:

$db1 = Db::connect('db1');
$db2 = Db::connect('db2');
$db1->query('select * from think_data where id = 1');
$db2->query('select * from think_data where id = 1');

参数绑定

实际开发中,可能某些数据使用的是外部传入的变量,为了让查询操作更加安全,我们建议使用参数绑定机
制,例如上面的操作可以改为:

Db::execute('insert into think_data (id, name ,status) values (?, ?, ?)', [8, 'thinkphp', 1]);
$result = Db::query('select * from think_data where id = ?', [8]);
dump($result);

也支持命名占位符绑定,例如:

Db::execute('insert into think_data (id, name , status) values (:id, :name, :status)',
['id' => 10, 'name' => 'thinkphp', 'status' => 1]);
$result = Db::query('select * from think_data where id=:id', ['id' => 10]);
dump($result);

—————————————————

查询构造器

查询构造器基于PDO实现,对不同的数据库驱动都是统一的语法。

ThinkPHP 5.0 查询构造器使用 PDO 参数绑定,以保护应用程序免于 SQL 注入,因此传入的参数不需额外转义特殊字符。

同样是实现上面的功能,我们可以改成:

// 插入记录
Db::table('think_data')
->insert(['id' => 18, 'name' => 'thinkphp', 'status' => 1]);
// 更新记录
Db::table('think_data')
->where('id', 18)
->update(['name' => "hello"]);
// 查询数据
$list = Db::table('think_data')
->where('id', 18)
->select();
// 删除数据
Db::table('think_data')
->where('id', 18)
->delete();

由于我们在数据库配置文件中设置了数据表的前缀为 think_ ,因此, table 方法可以改成 name 方法,
这样就不会因为数据表前缀的修改而改动 CURD 代码,例如:

// 插入记录
Db::name('data')
->insert(['id' => 18, 'name' => 'thinkphp']);
// 更新记录
Db::name('data')
->where('id', 18)
->update(['name' => "framework"]);
// 查询数据
$list = Db::name('data')
->where('id', 18)
->select();
dump($list);
// 删除数据
Db::name('data')
->where('id', 18)
->delete();
<pre>

如果使用系统提供的助手函数 db 则可以进一步简化查询代码如下:
<pre lang="php">
$db = db('data');
// 插入记录
$db->insert(['id' => 20, 'name' => 'thinkphp']);
// 更新记录
$db->where('id', 20)->update(['name' => "framework"]);
// 查询数据
$list = $db->where('id', 20)->select();
dump($list);
// 删除数据
$db->where('id', 20)->delete();
db 助手函数默认会每次重新连接数据库,因此应当尽量避免多次调用。

链式操作

使用链式操作可以完成复杂的数据库查询操作,例如:

// 查询十个满足条件的数据 并按照id倒序排列
$list = Db::name('data')
->where('status', 1)
->field('id,name')
->order('id', 'desc')
->limit(10)
->select();
dump($list);

链式操作不分先后,只要在查询方法(这里是 select 方法)之前调用就行,所以,下面的查询是等效的:

// 查询十个满足条件的数据 并按照id倒序排列
$list = Db::name('data')
->field('id,name')
->order('id', 'desc')
->where('status', 1)
->limit(10)
->select();
dump($list);

qq%e5%9b%be%e7%89%8720161207104106

事务支持

由于需要用到事务的功能,请先修改数据表的类型为 InnoDB ,而不是 MyISAM 。

对于事务的支持,最简单的方法就是使用 transaction 方法,只需要把需要执行的事务操作封装到闭包里
面即可自动完成事务,例如:

Db::transaction(function () {
Db::table('think_user')
->delete(1);
Db::table('think_data')
->insert(['id' => 28, 'name' => 'thinkphp', 'status' => 1]);
});

一旦 think_data 表写入失败的话,系统会自动回滚,写入成功的话系统会自动提交当前事务。
也可以手动控制事务的提交,上面的实现代码可以改成:

// 启动事务
Db::startTrans();
try {
Db::table('think_user')
->delete(1);
Db::table('think_data')
->insert(['id' => 28, 'name' => 'thinkphp', 'status' => 1]);
// 提交事务
Db::commit();
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
}
事务操作只对支持事务的数据库,并且设置了数据表为事务类型才有效,在Mysql数据库中请设置表类型为 InnoDB 。并且事务操作必须使用同一个数据库连接。
博主的文章或程序如果给您带来了价值,感谢您打赏一二
微信扫码支付 支付宝扫码支付

发表评论