未加星标

TOP4 - TP5数据库

字体大小 | |
[数据库(综合) 所属分类 数据库(综合) | 发布者 店小二04 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏
准备

5.0的数据查询由低到高分三个层次:

数据库原生查询(SQL查询);数据库链式查询(查询构造器);模型的对象化查询;

本章会涉及到前面两个,模型的查询会在第六章进行讲解。

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

然后,要查看数据库执行结果的话,访问下面的URL地址:

http://tp5.com/
数据库配置

我们给应用定义数据库配置文件(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操作。

在开始之前,我们首先在数据库demo中创建一个think_data数据表(这里以mysql数据库为例),SQL代码如下:

CREATE TABLE IF NOT EXISTS `think_data`(
`id` int(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL COMMENT '名称',
`status` tinyint(2) NOT NULL DEFAULT '0' COMMENT '状态',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
INSERT INTO `think_data`(`id`,`name`,`status`) VALUES
(1,'thinphp',1),
(2,'onethink',1),
(3,'topthink',1);
创建(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:[email protected]:3306/thinkphp#utf8')->query('select * 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);
查询构造器

除了原生查询外,5.0还提供了数据库查询构造器,可以更方便执行数据库操作,查询构造器基于PDO实现,对不同的数据库驱动都是统一的语法。

注意:

ThinkPHP5.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();

如果使用系统提供的助手函数db则可以进一步简化查询代码如下:

$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);

支持链式操作的查询方法包括:


方法名
描述
select
查询数据集
find
查询单个记录
insert
插入记录
update
更新记录
delete
删除记录
value
查询值
column
查询列
chunk
分块查询
count等
聚合查询

更多的链式操作方法可以参考官方的完全开发手册。

事务支持
注意:

由于需要用到事务的功能,请先修改数据表的类型为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。并且事务操作必须使用同一个数据库连接。

本文数据库(综合)相关术语:系统安全软件

主题: 数据服务器SQL数据库InnoDBSQL注入PHPAU删除CU
分页:12
转载请注明
本文标题:TOP4 - TP5数据库
本站链接:http://www.codesec.net/view/483018.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(35)