Loading

Thinkphp6.0 部分摘抄

Response

输出类型快捷方法对应Response类
HTML输出 response \think\Response
渲染模板输出 view \think\response\View
JSON输出 json \think\response\Json
JSONP输出 jsonp \think\response\Jsonp
XML输出 xml \think\response\Xml
页面重定向 redirect \think\response\Redirect
附件下载 download \think\response\File

返回json

<?php
namespace app\controller;

class Index
{
    public function hello()
    {
        $data = ['name' => 'thinkphp', 'status' => '1'];
        return json($data);
    }
}

返回html

<?php
namespace app\controller;

class Index
{
    public function hello()
    {
        $data = 'Hello,ThinkPHP!';
        return response($data);
    }
}

响应参数

设置头信息

json($data)->code(201)->header([
    'Cache-control' => 'no-cache,must-revalidate'
]);
方法名作用
lastModified 设置Last-Modified头信息
expires 设置Expires头信息
eTag 设置ETag头信息
cacheControl 设置Cache-control头信息
contentType 设置Content-Type头信息

写入cookie

response()->cookie('name', 'value', 600);

关闭缓存

// 关闭当前页面的请求缓存
json($data)->code(201)->allowCache(false);

重定向

如果是站内重定向的话,可以支持URL组装,有两种方式组装URL,第一种是直接使用完整地址(/打头)

redirect('/index/hello/name/thinkphp');

如果你需要自动生成URL地址,应该在调用之前调用url函数先生成最终的URL地址

redirect((string) url('hello',['name' => 'think']));

附加session闪存数据

<?php
namespace app\controller;

class Index
{
    public function index()
    {
        return redirect('/hello')->with('name','thinkphp');
    }
    
    public function hello()
    {
        $name = session('name');
        return 'hello,'.$name.'!';
    }    
}

重定向隐式传值使用的是Session闪存数据隐式传值,并且仅在下一次请求有效,再次访问重定向地址的时候无效。

记住重定向之前的地址和回溯重定向

<?php
namespace app\controller;

class Index
{
    public function index()
    {
        // 判断session完成标记是否存在
        if (session('?complete')) {
            // 删除session
            session('complete', null);
            return '重定向完成,回到原点!';
        } else {
            // 记住当前地址并重定向
            return redirect('hello')
                ->with('name', 'thinkphp')
                ->remember();
        }
    }

    public function hello()
    {
        $name = session('name');
        return 'hello,' . $name . '! <br/><a href="/index/index/restore">点击回到来源地址</a>';
    }

    public function restore()
    {
        // 设置session标记完成
        session('complete', true);
        // 跳回之前的来源地址
        return redirect()->restore();
    }
}

数据库

新版采用多类型的方式配置,方便切换数据库

type数据库
mysql MySQL
sqlite SqLite
pgsql PostgreSQL
sqlsrv SqlServer
mongo MongoDb
oracle Oracle

内置参数

PDO::ATTR_CASE              => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE           => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS      => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_EMULATE_PREPARES  => false,

在数据库配置文件中设置的params参数中的连接配置将会和内置的设置参数合并,如果需要使用长连接,并且返回数据库的小写列名,可以在数据库配置文件中增加下面的定义:

'params' => [
    \PDO::ATTR_PERSISTENT   => true,
    \PDO::ATTR_CASE         => \PDO::CASE_LOWER,
],

多个连接

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

动态选择数据库连接

\think\facade\Db::connect('demo')
    ->table('user')
    ->find();

配置参考参数

参数名描述默认值
type 数据库类型
hostname 数据库地址 127.0.0.1
database 数据库名称
username 数据库用户名
password 数据库密码
hostport 数据库端口号
dsn 数据库连接dsn信息
params 数据库连接参数
charset 数据库编码 utf8
prefix 数据库的表前缀
deploy 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 0
rw_separate 数据库读写是否分离 主从式有效 false
master_num 读写分离后 主服务器数量 1
slave_no 指定从服务器序号
fields_strict 是否严格检查字段是否存在 true
fields_cache 是否开启字段缓存 false
schema_cache_path 字段缓存目录
trigger_sql 是否开启SQL监听 true
auto_timestamp 自动写入时间戳字段 false
query 指定查询对象 think\db\Query

短线重连

// 开启断线重连
'break_reconnect' => true,

分布式数据库

多个数据库配置

return [
    'default'    =>    'mysql',
    'connections'    =>    [
        'mysql'    =>    [
            // 启用分布式数据库
            'deploy'   => 1,
            // 数据库类型
            'type'     => 'mysql',
            // 服务器地址
            'hostname' =>[ '192.168.1.1','192.168.1.2','192.168.1.3'],
            // 数据库名
            'database' => 'demo',
            // 数据库用户名
            'username' => 'root,slave,slave',
            // 数据库密码
            'password' => ['123456','abc,def','hello']
            // 数据库连接端口
            'hostport' => '',
            // 数据库字符集
            'charset'  => 'utf8',
        ],
    ],
];

设置读写分离

'rw_separate' => true,

发生下列情况,会主动连接主服务器

  • 使用了数据库的写操作方法(execute/insert/update/delete以及衍生方法);
  • 如果调用了数据库事务方法的话,会自动连接主服务器;
  • 从服务器连接失败,会自动连接主服务器;
  • 调用了查询构造器的lock方法;
  • 调用了查询构造器的master/readMaster方法

主从数据库的数据同步工作不在框架实现,需要数据库考虑自身的同步或者复制机制。

如果在大数据量或者特殊的情况下写入数据后可能会存在同步延迟的情况,可以调用master()方法进行主库查询操作。

代码调用主库

Db::name('user')
    ->where('id', 1)
    ->update(['name' => 'thinkphp']);
Db::name('user')
    ->master(true)
    ->find(1);

开启自动主库读取

// 开启自动主库读取
'read_master' => true,

开启后,一旦我们对某个数据表进行了写操作,那么当前请求的后续所有对该表的查询都会使用主库读取。

查询构造器

Db::table('think_user')->where('status', 1)->select()->toArray();
// 查不到以后抛出异常
Db::table('think_user')->where('status',1)->selectOrFail();
// 如果设置表前缀,使用name,而不是table
Db::name('user')->where('id', 1)->find();
Db::name('user')->where('status', 1)->select();
// 返回某个字段的值
Db::table('think_user')->where('id', 1)->value('name');

数据分批处理

Db::table('think_user')->chunk(100, function($users) {
    foreach ($users as $user) {
        //
    }
});

在闭包中返回false终止循环

Db::table('think_user')->chunk(100, function($users) {
    foreach ($users as $user) {
        // 处理结果集...
        if($user->status==0){
            return false;
        }
    }
});

游标查询

该查询方式利用了PHP的生成器特性,可以大幅减少大量数据查询的内存开销问题。

$cursor = Db::table('user')->where('status', 1)->cursor();
foreach($cursor as $user){
    echo $user['name'];
}

添加数据

$data = ['foo' => 'bar', 'bar' => 'foo'];
Db::name('user')->insert($data);
Db::name('user')->save($data);

mysql支持replace和返回自增id

Db::name('user')->replace()->insert($data);
$userId = Db::name('user')->insertGetId($data);

分批插入多条数据

$data = [
    ['foo' => 'bar', 'bar' => 'foo'],
    ['foo' => 'bar1', 'bar' => 'foo1'],
    ['foo' => 'bar2', 'bar' => 'foo2']
    ...
];
// 分批写入 每次最多100条数据
Db::name('user')
    ->limit(100)
    ->insertAll($data);

更新数据

Db::name('user')
    ->where('id', 1)
    ->update(['name' => 'thinkphp']);
Db::name('user')
    ->save(['id' => 1, 'name' => 'thinkphp']);

data方法传入要更新的数据

Db::name('user')
    ->where('id', 1)
    ->data(['name' => 'thinkphp'])
    ->update()

自增/自减

// score 字段加 5
Db::table('think_user')
    ->where('id', 1)
    ->inc('score', 5)
    ->update();

// score 字段减 1
Db::table('think_user')
    ->where('id', 1)
    ->dec('score')
    ->update();

删除数据

// 根据主键删除
Db::table('think_user')->delete(1);
Db::table('think_user')->delete([1,2,3]);

// 条件删除    
Db::table('think_user')->where('id',1)->delete();
Db::table('think_user')->where('id','<',10)->delete();

无条件删除:delete from table

// 无条件删除所有数据
Db::name('user')->delete(true);

软删除

// 软删除数据 使用delete_time字段标记删除
Db::name('user')
    ->where('id', 1)
    ->useSoftDelete('delete_time',time())
    ->delete();

查询表达式

表达式含义快捷查询方法
= 等于  
<> 不等于  
> 大于  
>= 大于等于  
< 小于  
<= 小于等于  
[NOT] LIKE 模糊查询 whereLike/whereNotLike
[NOT] BETWEEN (不在)区间查询 whereBetween/whereNotBetween
[NOT] IN (不在)IN 查询 whereIn/whereNotIn
[NOT] NULL 查询字段是否(不)是NULL whereNull/whereNotNull
[NOT] EXISTS EXISTS查询 whereExists/whereNotExists
[NOT] REGEXP 正则(不)匹配查询(仅支持Mysql)  
[NOT] BETWEEN TIME 时间区间比较 whereBetweenTime
> TIME 大于某个时间 whereTime
< TIME 小于某个时间 whereTime
>= TIME 大于等于某个时间 whereTime
<= TIME 小于等于某个时间 whereTime
EXP 表达式查询,支持SQL语法 whereExp
find in set FIND_IN_SET查询 whereFindInSet

链式调用

table

Db::field('user.name,role.title')
->table([
    'think_user'=>'user',
    'think_role'=>'role'
])
->limit(10)->select();

field

Db::table('user')->field('id,nickname as name')->select();
Db::table('user')->fieldRaw('id,SUM(score)')->select();

字段排除

Db::table('user')->withoutField('user_id,content')->select();
//或者用
Db::table('user')->withoutField(['user_id','content'])->select();

page

// 查询第一页数据
Db::table('article')->page(1,10)->select(); 
// 查询第二页数据
Db::table('article')->page(2,10)->select();
// page和limit一起使用
Db::table('article')->limit(25)->page(3)->select();

order

Db::table('user')
->where('status', 1)
->order(['order','id'=>'desc'])
->limit(5)
->select(); 

cache

cache可以用于selectfindvaluecolumn方法,以及其衍生方法,使用cache方法后,在缓存有效期之内不会再次进行数据库查询操作,而是直接获取缓存中的数据

Db::table('user')->where('id',5)->cache(true)->find();

缓存默认有效期是由默认的缓存配置参数决定的

Db::table('user')->cache(true,60)->find();
// 或者使用下面的方式 是等效的
Db::table('user')->cache(60)->find();

一旦数据更新或者删除后会自动清理缓存(下次获取的时候会自动重新缓存)

fetchSql

echo Db::table('user')->fetchSql(true)->find(1);

强制索引查询

Db::table('user')->force('user')->select();

partition

// 用于查询
Db::name('log')
    ->partition(['p1','p2'])
    ->select();

// 用于写入
Db::name('user')
    ->partition('p1')
    ->insert(['name' => 'think', 'score' => 100']);

sequence方法用于pgsql数据库指定自增序列名

Db::name('user')
->sequence('user_id_seq')
->insert(['name'=>'thinkphp']);

 extra,mysql中的DELAYED,IGNORE,ON DUPLICATE KEY UPDATE

Db::name('user')
    ->extra('IGNORE')
    ->insert(['name' => 'think']);

Db::name('user')
    ->extra('DELAYED')
    ->insert(['name' => 'think']);

Db::name('user')
    ->extra('SQL_BUFFER_RESULT')
    ->select();

DUPLICATE

Db::name('user')
    ->duplicate(['score' => 10])
    ->insert(['name' => 'think']);

procedure,是否是存储过程

$resultSet = Db::procedure(true)
    ->query('call procedure_name');

聚合查询

方法说明
count 统计数量,参数是要统计的字段名(可选)
max 获取最大值,参数是要统计的字段名(必须)
min 获取最小值,参数是要统计的字段名(必须)
avg 获取平均值,参数是要统计的字段名(必须)
sum 获取总分,参数是要统计的字段名(必须)

分页查询

// 查询状态为1的用户数据 并且每页显示10条数据
$list = Db::name('user')->where('status',1)->order('id', 'desc')->paginate(10);

// 渲染模板输出
return view('index', ['list' => $list]);

模板文件

<div>
<ul>
{volist name='list' id='user'}
    <li> {$user.nickname}</li>
{/volist}
</ul>
</div>
{$list|raw}

获取单独页总的数量

// 查询状态为1的用户数据 并且每页显示10条数据
$list = Db::name('user')->where('status',1)->order('id' ,'desc')->paginate(10);
// 获取总记录数
$count = $list->total();
return view('index', ['list' => $list, 'count' => $count]);

传入总结数,不会自动进行总数计算

// 查询状态为1的用户数据 并且每页显示10条数据 总记录数为1000
$list = Db::name('user')->where('status',1)->paginate(10,1000);
// 获取分页显示
$page = $list->render();

return view('index', ['list' => $list, 'page' => $page]);

分页后数据处理

$list = Db::name('user')->where('status',1)->order('id', 'desc')->paginate()->each(function($item, $key){
    $item['nickname'] = 'think';
    return $item;
});

模型数据操作,闭包中不需要返回值

$list = User::where('status',1)->order('id', 'desc')->paginate()->each(function($item, $key){
    $item->nickname = 'think';
});

时间比较

官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037565

高级查询

快捷查询

Db::table('think_user')
    ->where('name|title','like','thinkphp%')
    ->where('create_time&update_time','>',0)
    ->find();

批量查询

Db::table('think_user')
    ->where([
        ['name', 'like', 'thinkphp%'],
        ['title', 'like', '%thinkphp'],
        ['id', '>', 0],
        ['status', '=', 1],
    ])
    ->select();

如果使用exp,一定要使用raw

Db::table('think_user')
    ->where([
        ['name', 'like', 'thinkphp%'],
        ['title', 'like', '%thinkphp'],
        ['id', 'exp', Db::raw('>score')],
        ['status', '=', 1],
    ])
    ->select();
$map = [
        ['name', 'like', 'thinkphp%'],
        ['title', 'like', '%thinkphp'],
        ['id', '>', 0],
    ];
Db::table('think_user')
    ->where([ $map ])
    ->where('status',1)
    ->select();

闭包查询

$name = 'thinkphp';
$id = 10;
Db::table('think_user')->where(function ($query) use($name, $id) {
    $query->where('name', $name)
        ->whereOr('id', '>', $id);
})->select();

混合查询

Db::table('think_user')
    ->where('name', 'like', 'thinkphp%')
    ->where(function ($query) {
        $query->where('id', '<', 10);
    })
    ->select();

字符串条件查询

Db::table('think_user')
    ->whereRaw('id > 0 AND name LIKE "thinkphp%"')
    ->select();

参数绑定

Db::table('think_user')
    ->whereRaw('id > :id AND name LIKE :name ', ['id' => 0, 'name' => 'thinkphp%'])
    ->select();

快捷方法

方法作用
whereOr 字段OR查询
whereXor 字段XOR查询
whereNull 查询字段是否为Null
whereNotNull 查询字段是否不为Null
whereIn 字段IN查询
whereNotIn 字段NOT IN查询
whereBetween 字段BETWEEN查询
whereNotBetween 字段NOT BETWEEN查询
whereLike 字段LIKE查询
whereNotLike 字段NOT LIKE查询
whereExists EXISTS条件查询
whereNotExists NOT EXISTS条件查询
whereExp 表达式查询
whereColumn 比较两个字段

动态查询

动态查询描述
whereFieldName 查询某个字段的值
whereOrFieldName 查询某个字段的值
getByFieldName 根据某个字段查询
getFieldByFieldName 根据某个字段获取某个值
// 根据邮箱(email)查询用户信息
$user = Db::table('user')
    ->whereEmail('thinkphp@qq.com')
    ->find();

// 根据昵称(nick_name)查询用户
$email = Db::table('user')
    ->whereNickName('like', '%流年%')
    ->select();
    
// 根据邮箱查询用户信息
$user = Db::table('user')
    ->getByEmail('thinkphp@qq.com');
    
// 根据昵称(nick_name)查询用户信息
$user = Db::table('user')
    ->field('id,name,nick_name,email')
    ->getByNickName('流年');
    
// 根据邮箱查询用户的昵称
$nickname = Db::table('user')
    ->getFieldByEmail('thinkphp@qq.com', 'nick_name');
    
// 根据昵称(nick_name)查询用户邮箱
$email = Db::table('user')
    ->getFieldByNickName('流年', 'email');

条件查询

Db::name('user')->when($condition, function ($query) {
    // 满足条件后执行
    $query->where('score', '>', 80)->limit(10);
})->select();

满足条件的查询,不满足条件的查询

Db::name('user')->when($condition, function ($query) {
    // 满足条件后执行
    $query->where('score', '>', 80)->limit(10);
}, function ($query) {
    // 不满足条件执行
    $query->where('score', '>', 60);
});

视图查询

视图查询可以实现不依赖数据库视图的多表查询,并不需要数据库支持视图,是JOIN方法的推荐替代方法

Db::view('User', 'id,name')
    ->view('Profile', 'truename,phone,email', 'Profile.user_id=User.id')
    ->view('Score', 'score', 'Score.user_id=Profile.id')
    ->where('score', '>', 80)
    ->select();

默认是inner join,如果用left join

Db::view('User', 'id,name')
    ->view('Profile', 'truename,phone,email', 'Profile.user_id=User.id', 'LEFT')
    ->view('Score', 'score', 'Score.user_id=Profile.id', 'RIGHT')
    ->where('score', '>', 80)
    ->select();
Db::view(['think_user' => 'member'], ['id' => 'uid', 'name' => 'account'])
    ->view('Profile', 'truename,phone,email', 'Profile.user_id=member.id')
    ->view('Score', 'score', 'Score.user_id=Profile.id')
    ->where('score', '>', 80)
    ->select();

JSON字段

json插入

$user['name'] = 'thinkphp';
$user['info'] = [
    'email'    => 'thinkphp@qq.com',
    'nickname' => '流年',
];
Db::name('user')
    ->json(['info'])
    ->insert($user);

JSON数据查询

$user = Db::name('user')
    ->json(['info'])
    ->find(1);
dump($user);

JSON字段属性不会自动获取,可以手动设置类型

$user = Db::name('user')
    ->json(['info'])
    ->where('info->user_id', 10)
    ->setFieldType(['info->user_id' => 'int'])
    ->find();
dump($user);

json更新

$data['info'] = [
    'email'    => 'kancloud@qq.com',
    'nickname' => 'kancloud',
];
Db::name('user')
    ->json(['info'])
    ->where('id',1)
    ->update($data);

子查询

使用buildSql构造子查询

$subQuery = Db::table('think_user')
    ->field('id,name')
    ->where('id', '>', 10)
    ->buildSql();

使用子查询

Db::table($subQuery . ' a')
    ->where('a.name', 'like', 'thinkphp')
    ->order('id', 'desc')
    ->select();

闭包构造子查询

Db::table('think_user')
    ->where('id', 'IN', function ($query) {
        $query->table('think_profile')->where('status', 1)->field('id');
    })
    ->select();

原生查询

query方法用于执行SQL查询操作,返回查询结果数据集(数组)

Db::query("select * from think_user where status=:id", ['id' => 1]);

execute用于更新和写入数据的sql操作,如果数据非法或者查询错误则返回false,否则返回影响的记录数

// 参数绑定
Db::query("select * from think_user where id=? AND status=?", [8, 1]);
// 命名绑定
Db::execute("update think_user set name=:name where status=:status", ['name' => 'thinkphp', 'status' => 1]);

查询事件

事件描述
before_select select查询前回调
before_find find查询前回调
after_insert insert操作成功后回调
after_update update操作成功后回调
after_delete delete操作成功后回调
\think\facade\Db::event('before_select', function ($query) {
    // 事件处理
    return $result;
});

获取器

Db::name('user')->withAttr('name', function($value, $data) {
    return strtolower($value);
})->select();
$user = Db::name('user')
    ->json(['info'])
    ->withAttr('info.name', function($value, $data) {
        return strtolower($value);
    })->find(1);
dump($user);   

事务操作

闭包事务

Db::transaction(function () {
    Db::table('think_user')->find(1);
    Db::table('think_user')->delete(1);
});

手动控制

// 启动事务
Db::startTrans();
try {
    Db::table('think_user')->find(1);
    Db::table('think_user')->delete(1);
    // 提交事务
    Db::commit();
} catch (\Exception $e) {
    // 回滚事务
    Db::rollback();
}

XA事务实现分布式事务

Db::transactionXa(function () {
    Db::connect('db1')->table('think_user')->delete(1);
    Db::connect('db2')->table('think_user')->delete(1);
}, [Db::connect('db1'),Db::connect('db2')]);

存储过程

$resultSet = Db::query('call procedure_name');
foreach ($resultSet as $result) {

}
$resultSet = Db::query('call procedure_name(:in_param1,:in_param2,:out_param)', [
    'in_param1' => $param1,
    'in_param2' => [$param2, PDO::PARAM_INT],
    'out_param' => [$outParam, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 4000],
]);

获取数据集

返回的数据集对象是think\Collection,提供了和数组无差别用法,并且另外封装了一些额外的方法。

// 获取数据集
$users = Db::name('user')->select();
// 遍历数据集
foreach($users as $user){
    echo $user['name'];
    echo $user['id'];
}

通过isEmpty判断是否为空

$users = Db::name('user')->select();
if($users->isEmpty()){
    echo '数据集为空';
}

自定义数据库驱动

如果你需要自定义数据库驱动,需要自定义实现Connection类(或者继承think\db\Connection)和Builder类(或者继承think\db\Builder

对于特殊的驱动,可能还需要实现Query类(或者继承think\db\Query)

'type'  =>   'think\mongo\Connection',
'query' =>   'think\mongo\Query',
posted @ 2021-04-22 19:30  BigBender  阅读(421)  评论(0编辑  收藏  举报