专栏首页程序员小助手3分钟短文 | Laravel 自定义 SQL 查询参数绑定

3分钟短文 | Laravel 自定义 SQL 查询参数绑定

引言

laravel使用模型进行数据库操作时,并不是所有的字段或者关联关系 都能满足查询需求,有时候会有一些MySQL的函数计算等功能放在数据库 层面执行。

本文说一说自定义的参数绑定办法。

学习时间

假如有一个需求,已知经纬度手动计算两点之间的近距离。我们会使用类似下面的计算公式:

3959 * acos( cos( radians(  ?  ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(  ?  ) ) * sin( radians( lat ) ) )

其中问号位置就是我们需要填入的变量数据,也就是一个经纬度坐标,根据参照点,计算出数据库内每条记录内的该点距离参照点的距离。那么如果写到程序里,应该如何把绑定参数按顺序传入呢。

既然是自定义的字段名,我们可以使用 DB::raw 方式传入。代码如下:

$property =
    Property::select(
        DB::raw("title, lat, lng, (
            3959 * acos(
                cos( radians(  ?  ) ) *
                cos( radians( lat ) ) *
                cos( radians( lng ) - radians(?) ) +
                sin( radians(  ?  ) ) *
                sin( radians( lat ) )
            )
       ) AS distance")
    )
    ->having("distance", "<", "?")
    ->orderBy("distance")
    ->take(20)
    ->setBindings([$lat, $lng, $lat,  $radius])
    ->get();

这个查询语句有些复杂,可是有章可循。首先是使用select方法指定了返回字段名, 对于自定义的字段 distance 使用 having 子句进行进一步条件限定。最重要就是 setBindings 方法了,传送的是前面自定义SQL语句的位置参数。只需一一对应上就可以了。

如果大家经常使用laravel的调试功能的话,应该会注意到,这种问号的写法是laravel本身封装SQL语句用的。而对于写惯了PDO原生SQL语句查询的,则可以使用PDO方式的绑定方式:

$property = Property::select(DB::raw("title, lat, lng, ( 3959 * acos( cos( radians(:lat) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(:lng) + sin(radians(:lat_i) ) * sin( radians( lat ) ) ) ) AS distance"), ["lat" => $lat, "lng" => $lng, "lat_i" => $lat]);

上面的语句只用了select方法,其他的筛选和排序,与上一节代码相同,不需要调用 setBindings 方法。

为了方便查看,我们也可以不画蛇添足地使用 DB::raw 方法。而直接使用 selectRaw ,更为简洁直观:

$select = <<<SQL
    title,
    lat,
    lng,
    (3959*acos(cos(radians( ? ))*cos(radians(lat))*cos(radians(lng)-radians( ? ))+sin(radians( ? ))*sin(radians(lat)))) AS distance
SQL;

首先拼装好SQL语句的字段,然后使用laravel模型的方法:

$property = Property::selectRaw($select, [$lat, $lng, $lat])->having('distance', '<', $radius)->orderBy('distance')->take(20)->get();

写在最后

本文通过三种方式实现了laravel模型进行复杂的自定义查询, 其中提供了两种参数绑定的方式,我们推荐使用 selectRaw 的方式, 更为直观。

本文分享自微信公众号 - 程序员小助手(mql45ea),作者:黄门小李子

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 3分钟短文:Laravel 模型查询数据库的几个关键方法

    本期继续我们的laravel学习,主要说一说laravel使用eloquent orm 模型 读取数据库条目的几个常用方法。

    程序员小助手
  • 一行Python,你可以做什么?

    Python的列表推倒器是美好的语法糖。所以使用列表推倒器简化了for循环的嵌套,更简洁。许多黑魔法都是用这个方法。

    程序员小助手
  • 3分钟短文 | MySQL在分组时,把多列合并为一个字段!

    今天我们来说一个MySQL查询的例子,比如有一个统计需求, 分组后的数据,我们知道只能使用聚合函数进行统计, 那如果要根据分组约定,将一系列的值合并到单个字段显...

    程序员小助手
  • 测试思想-测试设计 测试用例设计之正交法

    用n个不同的拉丁字母排成一个n阶方阵(n<26 ),如果每行的n个字母均不相同,每列的n个字母均不相同,即每个字母在任一行、任一列中只出现一次,则称这种方阵...

    授客
  • 037android初级篇之Activity的几个重要函数

    手机屏幕事件的处理方法onTouchEvent。该方法在View类中的定义,并且所有的View子类全部重写了该方法,应用程序可以通过该方法处理手机屏幕的触摸事件...

    上善若水.夏
  • LeetCode 416. 分割等和子集(动态规划)

    给定一个只包含正整数的非空数组。 是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

    Michael阿明
  • Android Studio+MAT实战内存泄漏

    对于内存泄漏,在Android中如果不注意的话,还是很容易出现的,尤其是在Activity中,比较容易出现,下面我就说下自己是如何查找内存泄露的。

    砸漏
  • 新年到:Serverless帮你做贺卡

    怎么样,上面的这个小贺卡还不错吧?其实这个是通过Serverless架构自动生成的,测试地址:serverless.0duzhan.com

    Dfounderliu
  • 06:整数奇偶排序

    06:整数奇偶排序 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB描述 给定10个整数的序列,要求对其重新排序。排序要求: 1...

    attack
  • 力扣208——实现 Trie (前缀树)

    实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。

    健程之道

扫码关注云+社区

领取腾讯云代金券