• laravel框架如何优雅的写出文章的上一篇和下一篇


    上一页和下一页的原理

    以id排序,获取排序在当前id的上一篇文章的信息,以及当前id的下一篇文章的信息。

    一、简单直接方式

    $last = Article::where('id', '<', $info->id)->orderBy('id', 'desc')->first();
    $next = Article::where('id', '>', $info->id)->orderBy('id', 'asc')->first();
    

    能生成取到两个文章的数据。

    二、升级方式

    $last = Article::where('id', '<', $info->id)->latest('id')->first();
    $next = Article::where('id', '>', $info->id)->oldest('id')->first();
    

    使用laravel内置的latestoldest来代替orderBy,看起来优雅了一点,但是做的事情,跟上面的那个方式一样。分两次请求数据库,进而获取两篇文章信息。

    三、再次升级

    $sql = Article::where('id', '<', $info->id)->latest('id')->take(1);
    $list = Article::where('id', '>', $info->id)->oldest('id')->take(1)->union($sql)->orderBy('id', 'asc')->get();
    

    同样能获取到上一篇和下一篇的两篇文章。在不丢失优雅姿态的同时,使用union方法,将两个查询联合成了一个,减少了数据库的请求压力。
    同时使用orderBy的方法对查询到的两个数据,进行了排序。上一篇的文章信息就是下标为0的那只。下一篇的文章信息,就是下标为1的那只。

    使用下面的->dd()方式打印出的mysql的语句详情。

    $list = Article::where('id', '>', $info->id)->oldest('id')->take(1)->union($sql)->orderBy('id', 'asc')->dd();
    

    结果如下:

    (select * from `articles` where `id` > ? order by `id` asc limit 1) union (select * from `articles` where `id` < ? order by `id` desc limit 1) order by `id` asc
    
    array:2 [▼
      0 => 3
      1 => 3
    ]
    

    可以看出,就是两个查询联合成的一条语句查询。

    四、性能测试

    多谢大家踊跃的点赞和评论,有些小伙伴私信我说,使用union查询的时候,数据库不会使用索引。我也是抱着怀疑的态度,对自己的sql语句进行了EXPLAIN测试。

    EXPLAIN (select * from `articles` where `id` > 3 order by `id` asc limit 1) union (select * from `articles` where `id` < 3 order by `id` desc limit 1) order by `id` asc
    

    下面是测试的结果,虽然我的数据量不大,但是就数据库给我的反馈,我们也能看懂一二。

    结论

    1. id为1和2的possible_keyskey的值都是PRIMARY,这就足以说明,查询articles的时候,使用的是索引查询,而且是主键索引。
    2. 也就意味着,几十在数据量很大的情况下,查出这两篇文章的速度也都相对客观。
    3. 第三条记录是最外层的union,它是没有使用索引。因为它也没有索引可用,它表是<union1, 2>,它是个临时生成的表,里面只有上面查询的两条记录。这也就意味着,articles表的数据量的大小,对它的影响不大。
    4. Extra字段中的Using temporayr是数据库为了解决查询,创建一个临时表来容纳结果。Using filesort是做最后一次排序使用的,如果对结果不进行排序的话,是没有Using filesort显示的。
  • 相关阅读:
    linux 读写文件 open write lseek的API和应用
    gdb 常用命令
    makefile
    c/c++ 动态库与静态库的制作和使用
    linux 常用命令
    c/c++ 网络编程 陈硕老师视频理解之ttcp
    emacs 高亮
    初识HMTL标签
    Java集合基于JDK1.8的ArrayList源码分析
    Java提高篇——equals()与hashCode()方法详解
  • 原文地址:https://www.cnblogs.com/hxsen/p/12717008.html
Copyright © 2020-2023  润新知