侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

ThinkPHP:数据查询的基本原则

ThinkPHP  /  管理员 发布于 8年前   343

对于本文涉及到的数据查询的几个基本原则请尽量纳入你的项目规范,也是官方倡导的最佳实践。在此之前,我希望你已经看过之前的一篇博客:「 你真的了解Db类和模型的正确使用姿势么? 」。

尽量不要使用数组条件查询

大部分混乱的查询语法都是使用了数组查询导致的,而5.1的数组条件查询用法又和5.0是完全不同的,如果你习惯了5.0的数组查询方式,建议你阅读下这篇文章:「 教你使用5.1的数组对象查询 」。

下面可能是很多新手比较容易犯的一个查询错误。

$where['id'] = ['in', '1,2,3'];User::where($where)->select();

显然,这个查询思维深受老版本的影响。5.1版本的查询语法相比较5.0来说,更加对象化,下面的这种才是正确的用法。

$where['id'] = [1,2,3];User::where($where)->select();

也许是因为PHP的数组太好用的缘故,很多人对数组查询条件乐此不疲(或者是对象焦虑?)。但如果你正确的使用查询构造器以及配合模型的相关特性,可以让你的查询逻辑变得更清晰,也更加易于维护。

而且,在一些较为复杂的查询条件下,你无法使用数组完成查询,例如下面的查询用法。

User::where('id', '>', 100)    ->whereOr('id', '<', 10)    ->where('name', 'like', 'think%')    ->whereColumn('name', 'nickname')    ->when('80'== $condition, function ($query) {        $query->where('score', '>', 80)->limit(10);    })->select();

所以,除非你很清楚5.1的数组查询用法,否则请尽量不要用数组条件查询了。

安全使用字符串查询条件

在使用字符串查询条件的时候,如果存在外部变量,请务必使用参数绑定,并最好使用whereRaw方法,该方法可以和其它的查询构造器方法混合使用。

User::whereRaw("id = :id AND name = :name", [        'id' => [$id, \PDO::PARAM_INT] ,         'name' => $name    ])->where('status', 1)    ->order('id', 'desc')    ->select();

对于一些比较在意性能的查询,你也可以直接使用query或者execute方法,但同样也要注意参数的安全以及考虑不同数据库的移植问题。

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

对使用了SQL函数的查询采用Raw机制

如果你的查询里面包含了SQL函数,那么请使用whereRaw(或者whereExp)、orderRaw或者fieldRaw方法。

User::whereExp('nickname', "= CONCAT(name, '-', id)")    ->orderRaw("field(name,'thinkphp', 'kancloud')")    ->fieldRaw('id,SUM(score)')    ->select();

合理运用闭包,但不要滥用

闭包查询在查询构造器中有一些特殊用途,但如非必要,也无需滥用。

闭包查询的典型使用场景包括下面几个。

条件查询中通常都用闭包来表示一组条件查询。

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

在一些子查询中经常会用到闭包。

User::whereIn('id', function ($query) {    $query->table('profile')        ->where('name', 'like', 'think%')        ->field('id');})->select();

生成一组闭合的查询条件

User::where('id', '>', 100)    ->whereOr(function($query) {        $query->where('name', 'like', 'think%')        ->whereColumn('name', 'nickname');    })->select();

在这个查询用法中,闭包里面的查询条件会在两边加上括号而成为一个闭合的查询条件。

在很多的关联预载入查询中可以通过闭包来进行关联数据的筛选。

User::with(['profile' => function($query) {$query->field('user_id,email,phone');}])->select([1,2,3]);

尽量复用你的查询条件

所有的查询条件应该做到一处定义多处复用,例如封装到模型的方法里面,尤其不要直接把一堆复杂的查询条件写到你的控制器代码,否则一旦业务调整,满世界的搜索代码改变你的查询条件将会是一场噩梦。

你也许在官方的手册或者一些教程中看到很多在控制器里面直接封装查询条件的写法,但那仅仅是出于方便展示用法的需要,并不可取。

在一些中大型的应用架构设计中,通常会把模型分成数据层、逻辑层和服务层,控制器只会调用服务层方法。而查询逻辑则基本上被封装到逻辑层里面,数据层仅仅是做模型的各种定义。

而在简单的应用里面,也可以采用PHP的Trait机制来实现代码的复用机制。

用查询范围或搜索器简化查询

如果你使用模型查询的话,把你的查询条件尽量封装到查询范围或者搜索器方法里面,查询范围和搜索器的区别主要在于查询范围比较适合定义一组(多个字段)查询条件,如果要调用多个查询范围需要多次调用,而搜索器比较适合定义一个字段(其实并非绝对)的查询条件,只需要调用一次withSearch方法。

使用查询范围和搜索器的例子。

<?phpnamespace app\index\model;use think\Model;class User extends Model{    public function scopeVip($query)    {        $query->where('user_type', 'vip')            ->where('status', 1)            ->field('id,name');    }        public function searchAgeAttr($query, $age)    {        $query->where('age','>',$age);    }            public function searchScoreAttr($query, $score)    {        $query->where('score','<=',$score)->where('score', '>' ,0);    }    }

控制器代码

<?phpnamespace app\index\controller;use think\Controller;use think\Request;class index extends Controller{    public function index(Request $request)    {        // 查询VIP会员        User::vip()->select();        // 查询年龄和分数        User::withSearch(['age,'score''], $request->param())->select();    }}

在控制器代码中,我们只关注业务逻辑本身,而不需要关注这个逻辑内部的查询条件是什么。更详细的关于搜索器和查询范围的内容可以参考官方手册。

,有大量免费的ThinkPHP入门教程,欢迎大家学习!

本文转自:https://blog.thinkphp.cn/833794

以上就是ThinkPHP:数据查询的基本原则的详细内容,更多请关注其它相关文章!


  • 上一条:
    一文了解ThinkPHP6.0之中间件
    下一条:
    ThinkPHP的安全注意事项
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • thinkphp + mongodb项目中数据加载慢问题分析及解决(0个评论)
    • thinkphp6框架中封装redis操作类(0个评论)
    • thinkphp6框架中实现定时任务功能流程步骤(0个评论)
    • Thinkphp5.1框架中实现Session+Redis会话共享流程步骤(0个评论)
    • TP5框架版本5.0.10安全漏洞根据官方补丁修复,也是本站安全漏洞修复(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-12
    • 2018-01
    • 2018-02
    • 2020-03
    • 2021-07
    • 2021-12
    • 2022-05
    • 2022-06
    • 2022-09
    • 2023-01
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客