ThinkPHP5.1 数据库的配置
1. 静态配置: 在config/database.php,数据库配置文件中进行配置
最关键的参数就是下面几个(其它参数后面会陆续涉及):
参数名 作用
type 数据库类型或者连接类名(一般为mysql)
hostname 数据库服务器地址(一般是IP地址,默认为127.0.0.1)
username 数据库用户名(默认为root)
password 数据库用户密码(默认为空)
database 使用的数据库名称
charset 数据库编码(默认为utf8)
2. 动态配置: 在Db类或者Query类的connect方法中传入动态的配置参数
ThinkPHP5.1 数据库的简单操作
1. 开启数据库调用模式:'debug' => true
2. 连接数据库: config/database.php
3. 导入Db类: use think\Db;
4. 在控制器中使用Db类静态调用原生查询方法query/execute进行测试
注: 原生查询仅仅使用到了连接器类,与查询器类无关
重点注意:
1. 数据库操作主要分为连接,生成SQL查询语句与执行三部分
2. 连接器主要完成: 数据库的连接与SQL语句的执行
3. 查询器主要是负责接收参数并调用生成器生成SQL语句,不负责执行
4. 如果你只用原生查询,实际上全部操作都是在连接器Connection中完成的。
1. 测试数据库是否连接成功
<?php namespace app\index\controller;//命名空间 //引入数据库配置文件 use think\Db; //简单的数据库操作 class Index { public function select() { //测试数据库是否连接成功 dump(Db::query("select * from staff")); } }
测试结果:
查询:不仅仅是读,还包括写,CURD:增删改查
原生查询:只用到连接器类Connection中的query()读操作:select
execute()专用于写操作:新增 更新 删除
2. ThinkPHP5.1 数据库的原生查询
原生查询表中,年龄大于30的员工信息 public function select() { //A.使用占位符? $sql = "SELECT name AS 姓名,age AS 年龄 FROM staff WHERE age>? LIMIT ?;"; //参数绑定:参数由索引数组表示,元素顺序与占位符顺序必须一一对应 $res = Db::query($sql,[30,5]); //查看查询结果:自动将结果解析为二维数组输出 dump($res); }
//原生查询表中,工资大于5000的员工信息
public function select() { //B.使用命名占位符: $sql = "SELECT name AS 姓名,salary AS 工资 FROM staff WHERE salary>:salary LIMIT :num ;"; //参数绑定:参数由关联数组表示,键名与命名占位符一致,顺序无所谓 $res = Db::query($sql,['num'=>5,'salary'=>5000]); dump($res); }
//跟踪器中查看生成的SQL语句,发现参数的类型并不匹配,因为参数默认为字符型,需要转换为数值
//只需要修改一下参数绑定语句,给参数值传递第二个参数:PDO参数常量,进行类型限定
public function update() { $sql = "SELECT name AS 姓名,salary AS 工资 FROM staff WHERE salary>:salary LIMIT :num ;"; $res = Db::query($sql,['num'=>[5, \PDO::PARAM_INT],'salary'=>[5000,\PDO::PARAM_INT]]); dump($res); }
//更新表中 ID为10的员工,工资修改为8000
public function update() { // //将id=10的员工,工资修改为6500 $sql = "UPDATE staff SET salary = :salary WHERE staff_id = :staff_id ;"; Db::execute($sql,['salary'=>[8000,\PDO::PARAM_INT], 'staff_id'=>[10, \PDO::PARAM_INT]]); // //如果失败会自动中止运行,抛出异常 return '更新成功'; }
3.ThinkPHP5.1 数据库的查询构造器查询
一、查询类的自动链式调用
1.查询类就是think\db\Query类,自动实例化查询类,无需手动实例化。
2.调用Db类的任何方法都会自动实例化查询类,并由查询类自动实例化连接器类执行查询。
二、必须熟练掌握的10大查询方法
1. table(): 指定要查询的完整表名
$res = Db::table('staff')
name()可以省略掉前缀,因为我的表没有前缀,也没有database.php中设置前缀,所以不用它
推荐数据表不要加前缀,也不要用name(),用table()完全满足要求
2. field(): 指定查询字段 如果要指定查询的字段使用field()方法
->field(['name'=>'姓名','sex'=>'性别','age'=>'年龄']) //可设置字段别名
3. where(): 指定查询条件 (字段名,表达式,查询条件),表达式为=号,可以省略,相等是默认值
//->where('staff_id','=',11) ->where('staff_id',11) //两句效果一样 等号可以省略
//where()支持直接传入字符串为查询条件
4. order(): 指定结果排序 DESC 降序 ASC 默认升序
//order()支持字符串 ->order('salary DESC') //order()也支持数组 ->order('salary','DESC')
5. limit(): 指定查询结果数
->limit(5)
6. find(): 查询一条记录
public function find() { $res = Db::table('staff') ->field(['name'=>'姓名','sex'=>'性别','age'=>'年龄']) // 参数可使用数组 可设置字段别名 ->where('staff_id',11) ->find(); dump($res); }
7. select(): 查询数据集
public function select() { //查询满足条件的多条记录select() $res = Db::table('staff') ->field(['name'=>'姓名','age'=>'工资']) ->where('age','>',3000) //where()支持直接传入字符串为查询条件 ->order('age','DESC') ->limit(8) ->select(); dump($res); }
8. insert(): 写入数据
public function insert() { //新增单条记录 新增前不需要查询操作 //准备要添加的数据,以关联数组的形式 $data = [ 'name' => '潘金莲', 'sex' => 1, 'age' => 30, 'salary' => 2000 ]; //使用data()方法将要新增的记录进行打包,尽量不要在最终方法中传入参数 $num = Db::table('staff')->data($data)->insert(); //新增纪录的ID $id = Db::getLastInsID(); //判断是否添加成功 并显示成功添加记录的主键 return $num ? '添加成功,id='.$id : '没有记录被添加'; }
public function insert() { //新增多条记录 insertAll(),语法与新增单条基本一致 //新增多条记录,返回新增记录的数量 $data = [ ['name' => '张辽','sex' => 0,'age' => 38,'salary' => 6900], ['name' => '赵云','sex' => 0,'age' => 27,'salary' => 5200], ['name' => '黄忠','sex' => 0,'age' => 83,'salary' => 5800], ['name' => '许绪','sex' => 0,'age' => 53,'salary' => 4700], ['name' => '吕布','sex' => 0,'age' => 33,'salary' => 18000], ['name' => '貂蝉','sex' => 1,'age' => 18,'salary' => 2700], ]; $num = Db::table('staff')->data($data)->insertAll(); return $num ? '添加成功'.$num.'条记录~~' : '没有记录被添加'; }
9. update(): 更新数据
public function update() { //更新操作必须是基于前置查询,不允许无条件更新 //更新操作使用的是update()方法 //例如:将工资小于等于2000的,加薪2000 $num = Db::table('staff') ->where('salary','<=',2000) //这里要引用原salary字段的值,所以要用到Db::raw()引用原始数据 ->data(['salary'=> Db::raw('salary+2000')]) ->update(); return $num ? '更新成功'.$num.'条记录~~' : '没有记录被更新'; }
更新已存在的记录的值时 直接根据主键更新
public function update() { $num = Db::table('staff') //如果更新记录中存在主键,则直接根据主键更新 ->update(['age'=>27,'staff_id'=>14]); return $num ? '更新成功'.$num.'条记录~~' : '没有记录被更新'; }
注:主键不可更新
10.delete(): 删除数据
public function delete() { //删除也更新操作一样,也必须是基于前置查询,绝不允许无条件删除 //删除操作使用:delete()方法 $num = Db::table('staff')->where('salary','>',10000)->delete(); return $num ? '删除成功'.$num.'条记录~~' : '没有记录被删除'; }
//如果想删除全部记录,可直接给delete()方法传入true: delete(true)
// $num = Db::table('staff')->delete(true);
//提醒: 删除数据是非常危险的操作,强烈建议使用框架提供的软删除来实现,即用更新来模拟删除
知识点:
数据库操作入口类Db think\Db.php:仅仅做为数据库操作的入口
底层是通过一个__callStatic()方法来实现各种查询操作的,仅在需要操作数据库的时候才会真正连接数据库,是真正的惰性连接
ThinkPHP5.1数据库操作的三大核心组件和功能
一. Connection: 连接器类, think\db\Connection
连接器类的作用:1.连接数据库 2.获取数据表和字段信息 3.基础查询(原生查询) 4.事务支持 5.分布式支持;
内置的支持:
Mysql think\db\connector\Mysql Pgsql think\db\connector\Pgsql
Sqlite think\db\connector\Sqlite Sqlsrv think\db\connector\Sqlsrv
如果仅仅进行原生查询,实际上只需要连接器类就足够了,用Db类直接调用
二. Query: 查询器类, think\db\Query
1.除了原生查询可以在连接类完成之外,其它的查询都是调用查询类的方法完成;
2.它衔接了连接类和生成类,统一了查询用法,所以查询类是不需要单独驱动配合的,我们也称之为查询器;
3.无论采用什么数据库,我们的查询方式是统一的;
4.Query类封装了所有的数据库CURD方法的优雅实现,包括链式方法及各种查询,并自动使用了PDO参数绑定
5.参数自动绑定是在生成器类解析生成SQL时完成,最大程度地保护你的程序避免受数据库注入攻击,查询操作
会调用生成类生成对应数据库的SQL语句,然后再调用连接类提供的底层原生查询方法执行最终的数据库查询操作
6.所有的数据库查询都使用了PDO的预处理和参数绑定机制。你所看到的大部分数据库方法都来自于查询类
而并非Db类,这一点很关键;
7.也就是说虽然我们始终使用Db类操作数据库,而实际上大部分方法都是由查询器类提供的方法。
三. Builder: 生成器类, think\db\Builder
1.生成类的作用是接收Query类的所有查询参数,并负责解析生成对应数据库的原生SQL语法,然后返回给
Query类进行后续的处理(包括交给连接类进行SQL执行和返回结果处理),也称为(语法)生成器。
2.生成类的作用其实就是解决不同的数据库查询语法之间的差异。
3.[查询类实现了统一的查询接口,而生成类负责数据库底层的查询对接。]
4.生成类一般不需要自己调用,而是由查询类自动调用的。也可以这么理解,生成类和查询类是一体的,
5.事实上它们合起来就是通常我们所说的查询构造器(因为实际的查询操作还是在连接器中执行的)