ThinkPHP入门-数据库
- 参考:ThinkPHP5快速入门-数据库。
- 以下为个人看文档的总结,备不时之需,需要的请转1中的参考文献。
- 学习的时候以5.1版本作为学习的版本。
- 本节主要内容为数据库相关知识,但是貌似没有看到ORM的相关知识,最后提到了一些关于表格事物支持的一点知识,应该可以略过直接到关联查询部分。
- 侵删
一、概述
-
5.0版本的数据库查询由低到高分为三个层次,分别为
1)数据库原生查询(SQL查询);
2)数据库链式查询(查询构造器);
3)模型的对象化查询。
其中前两个在这一节介绍,模型的在第六节介绍 -
在使用Db类进行数据库的查询之前,首先必须创建一个控制器类,以及一个操作方法用于测试,当然前提得有该数据库。
<?php namespace app\index\controller; use think\Db; class Index { public function index() { // 后面的数据库查询代码都放在这个位置 } }
可以定义路由,然后查看当前的执行的结果,在开始之前首先要建立一个数据库,本文采用的是
mysql
数据库,并建立了一个名文demo的本地数据库,下面语句为在数据库中创建一个think_data的数据表,并插入数据。// 创建表格 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,'thinkphp',1), (2,'onethink',1), (3,'topthink',1);
二、数据库配置
-
数据库配置主要是咋定义数据库的配置文件中,在5.1版本主要是在
config/database.php
中,这里是直接配置到文件中,在其他的框架是配置到了一个.env
文件中,说是避免将数据库账号密码制成明文。return [ // 数据库类型 'type' => 'mysql', // 服务器地址 'hostname' => '127.0.0.1', // 数据库名 'database' => 'test', // 数据库用户名 'username' => 'root', // 数据库密码 'password' => '', // 数据库连接端口 'hostport' => '3306', // 数据库连接参数 'params' => [], // 数据库编码默认采用utf8 'charset' => 'utf8', // 数据库表前缀 'prefix' => '', // 数据库调试模式 'debug' => true, ];
-
如果使用了多个模块,并且不同的模块采用不同的数据库连接,那么可以在每个模块的目录下面单独定义数据库的配置,下面的实例,主要是在
application/index/database.php
,也就是index的模块下进行的配置,并且模块数据库的配置中使用了长链接。
1)模块的数据库的配置文件只是需要配置和全局数据库配置文件差异的部分,相同的部分不需要重复配置,可能是因为局部变量能替代全局变量的缘故吧。
2)5.1版本中的模块的数据库配置文件应该放到application/index/config/database.php
中。return [ // 数据库名 'database' => 'demo', // 数据库表前缀 'prefix' => 'think_', // 数据库连接参数 'params' => [ // 使用长连接 \PDO::ATTR_PERSISTENT => true, ], ];
三、原生查询
- 原生的还是比较少用的,一般都会使用ORM框架来操作数据库吧。
3.1 原生查询
- 设置好数据库的连接信息之后,就可以直接进行原生的SQL的查询操作了,包括
query
和execute
两个方法,分别用于查询操作和鞋操作,下面我们来实现数据表的think_data
的CURD操作。 - 创建操作,也是插入记录
$result = Db::execute('insert into think_data (id, name ,status) values (5, "thinkphp",1)');
dump($result);
- 更新操作
$result = Db::execute('update think_data set name = "framework" where id = 5 ');
dump($result);
- 读取操作,query方法返回的是一个数据集(数组),如果没有查询到数据则返回空数组
$result = Db::query('select * from think_data where id = 5');
dump($result);
- 删除操作
$result = Db::execute('delete from think_data where id = 5 ');
dump($result);
3.2 其它操作
-
可以执行一些凄然的数据库操作,原则上,读操作都是使用的query,写操作使用的execute方法即可。
query
方法用于查询,默认情况下返回的是数据集(二维数组),execute
方法返回的是影响记录数。// 显示数据库列表 $result = Db::query('show tables from demo'); dump($result); // 清空数据表 $result = Db::execute('TRUNCATE table think_data'); dump($result);
3.3 切换数据库
-
在进行数据库查询的时候,支持切换数据库进行查询。
$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);
-
为了简化代码,通常的做法是事先在配置文件中定义好多个数据库的连接配置,例如我们在应用配置文件(config/database.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类的时候还是使用默认的数据库连接,如果需要多次切换数据库查询,可以使用变量来获取不同数据库的连接connect
方法必须直接直接进行查询,不可以使用Db::query
查询????$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::connect('db1'); Db::query('select * from think_data where id = 1');
3.4 参数绑定
-
实际的开发中,可能某些的数据使用的是外部传入的变量,为了让查询操作更加安全,建议的使用的是参数绑定机制,也吃吃命名占位绑定符。
// 参数绑定机制 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') ->field('name,email') ->where('id', 18) ->select(); // 删除数据 Db::table('think_data') ->where('id', 18) ->delete();
-
由于我们在数据库配置文件中设置了数据表的前缀为
think_
,因此,table
方法可以改成为name
方法,这样就不会因为数据表的前缀而改动CRUD的代码。// 插入记录 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
,可以进一步简化查询代码,感觉还是助手函数比较简便,但是,又有但是,23333,db助手在5.0.9之前的版本默认每次重新连接数据库,因此还不能多次调用,好鸡肋。$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();
五、链式操作
-
这个链式操作就是可以完成复杂的数据库的查询操作
// 查询十个满足条件的数据 并按照id倒序排列 $list = Db::name('data') ->where('status', 1) ->field('id,name') ->order('id', 'desc') ->limit(10) ->select(); dump($list);
-
链式操作不分先后,只要在查询方法之前调用之前调用就行。
-
支持链式操作的方法都有:select(查询数据集)、find(查询单个记录)、insert(插入记录)、update(更新记录)、delete(删除记录)、value(查询值)、column(查询列)、chunk(分块查询)、count(聚合查询)…
六、事物支持
-
由于需要用到事物支持,需要先修改数据表的类型为
InnoDB
,而不是MyISAM
,这个数据表的类型参数没找到,这个参数是在创建表格的时候,最后有一个engine
的参数,这个参数通常为MyISAM
,这个参数为新建数据表的储存引擎,而MyISAM
不支持事物操作,需要将引擎的类型改为InnoDB
。 -
对于事物的支持,最简单的方法就是使用
transaction
方法,只需要把需要执行的事物操作封装到闭包里面即可自动完成事物Db::transaction(function () { Db::table('think_user') ->delete(1); Db::table('think_data') ->insert(['id' => 28, 'name' => 'thinkphp', 'status' => 1]); });
-
这样的好处是,一旦
think_data
表写入失败的情况下,系统就可以自动回滚,写入成功的话,系统会自动提交当前的事物,也可以手动控制事物的提交。
事物操作只对支持事物的数据库,并且设置了数据表为事物类型的才有效,在MySql数据表中请设置表的储存引擎的类型为InnoDB
。并且事物操作必须使用同一个数据库连接。// 启动事务 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(); }