【问题标题】:Laravel cursorPagination returns results with a mix of array and objectsLaravel cursorPagination 返回包含数组和对象的结果
【发布时间】:2022-01-30 06:47:49
【问题描述】:

我在 Livewire 组件中实现了无限分页,我注意到在初始页面加载时它正在加载对象,但是当我滚动并加载更多数据时,它会将数组添加到集合中,所以我最终得到了一个集合具有数组和对象的混合值。知道如何解决这个问题,以便它唯一的对象吗?我希望拥有所有对象的原因是我在视图中使用了一个方法,如果它是一个数组,我就无法访问它。

/**
     * Loads more blog posts.
     *
     * @return void
     */
    public function loadBlogs()
    {
        if ($this->hasMorePages !== null  && !$this->hasMorePages) {
            return;
        }

        if ($this->category_id) {
            $posts = BlogPost::where('user_id', request()->user()->id)
                ->where('category_id', $this->category_id)
                ->with('category')
                ->orderBy('id', 'desc')
                ->cursorPaginate(16, ['*'], 'cursor', Cursor::fromEncoded($this->nextCursor));
        } else {
            $posts = BlogPost::where('user_id', request()->user()->id)
                ->with('category')
                ->orderBy('id', 'desc')
                ->cursorPaginate(16, ['*'], 'cursor', Cursor::fromEncoded($this->nextCursor));
        }

        $this->blogPosts->push(...$posts->items());

        $this->hasMorePages = $posts->hasMorePages();

        if ($this->hasMorePages === true) {
            $this->nextCursor = $posts->nextCursor()->encode();
        }
    }

dd:

Illuminate\Support\Collection {#1751 ▼
  #items: array:32 [▼
    0 => array:10 [▶]
    1 => array:10 [▶]
    2 => array:10 [▶]
    3 => array:10 [▶]
    4 => array:10 [▶]
    5 => array:10 [▶]
    6 => array:10 [▶]
    7 => array:10 [▶]
    8 => array:10 [▶]
    9 => array:10 [▶]
    10 => array:10 [▶]
    11 => array:10 [▶]
    12 => array:10 [▶]
    13 => array:10 [▶]
    14 => array:10 [▶]
    15 => array:10 [▶]
    16 => App\Models\BlogPost {#1775 ▶}
    17 => App\Models\BlogPost {#1776 ▶}
    18 => App\Models\BlogPost {#1777 ▶}
    19 => App\Models\BlogPost {#1778 ▶}
    20 => App\Models\BlogPost {#1779 ▶}
    21 => App\Models\BlogPost {#1780 ▶}
    22 => App\Models\BlogPost {#1781 ▶}
    23 => App\Models\BlogPost {#1782 ▶}
    24 => App\Models\BlogPost {#1783 ▶}
    25 => App\Models\BlogPost {#1784 ▶}
    26 => App\Models\BlogPost {#1785 ▶}
    27 => App\Models\BlogPost {#1786 ▶}
    28 => App\Models\BlogPost {#1787 ▶}
    29 => App\Models\BlogPost {#1788 ▶}
    30 => App\Models\BlogPost {#1789 ▶}
    31 => App\Models\BlogPost {#1790 ▶}
  ]
  #escapeWhenCastingToString: false
}

【问题讨论】:

    标签: laravel pagination laravel-livewire laravel-collection


    【解决方案1】:

    我使用Illuminate\Support\Collection,我改为Illuminate\Database\Eloquent\Collection,而不是使用collect()来设置我使用new Collection()的初始集合

    结果是这样的:

    Illuminate\Database\Eloquent\Collection {#1805 ▼
      #items: array:32 [▼
        0 => App\Models\BlogPost {#1789 ▶}
        1 => App\Models\BlogPost {#1790 ▶}
        2 => App\Models\BlogPost {#1791 ▶}
        3 => App\Models\BlogPost {#1792 ▶}
        4 => App\Models\BlogPost {#1793 ▶}
        5 => App\Models\BlogPost {#1794 ▶}
        6 => App\Models\BlogPost {#1795 ▶}
        7 => App\Models\BlogPost {#1796 ▶}
        8 => App\Models\BlogPost {#1797 ▶}
        9 => App\Models\BlogPost {#1798 ▶}
        10 => App\Models\BlogPost {#1799 ▶}
        11 => App\Models\BlogPost {#1800 ▶}
        12 => App\Models\BlogPost {#1801 ▶}
        13 => App\Models\BlogPost {#1802 ▶}
        14 => App\Models\BlogPost {#1803 ▶}
        15 => App\Models\BlogPost {#1804 ▶}
        16 => App\Models\BlogPost {#1786 ▶}
        17 => App\Models\BlogPost {#1787 ▶}
        18 => App\Models\BlogPost {#1788 ▶}
        19 => App\Models\BlogPost {#1717 ▶}
        20 => App\Models\BlogPost {#1764 ▶}
        21 => App\Models\BlogPost {#1755 ▶}
        22 => App\Models\BlogPost {#1813 ▶}
        23 => App\Models\BlogPost {#1814 ▶}
        24 => App\Models\BlogPost {#1815 ▶}
        25 => App\Models\BlogPost {#1816 ▶}
        26 => App\Models\BlogPost {#1817 ▶}
        27 => App\Models\BlogPost {#1818 ▶}
        28 => App\Models\BlogPost {#1819 ▶}
        29 => App\Models\BlogPost {#1820 ▶}
        30 => App\Models\BlogPost {#1821 ▶}
        31 => App\Models\BlogPost {#1822 ▶}
      ]
      #escapeWhenCastingToString: false
    }
    

    **编辑

    使用Illuminate\Database\Eloquent\Collection 会带来性能问题。以下是查询的样子:

    select * from
    'blog posts' where 'blog_posts'. 'id' in (10103, 10102, 10101, 10100, 10099, 10098,
    10097, 10096, 10095, 10094, 10093, 10092, 10091, 10090, 10089, 10088, 10087, 10086, 10085, 10084
    10083, 10082, 10081, 10080, 10079, 10078, 10077, 10076, 10075, 10074, 10073, 10072, 10071, 10070,
    10069, 10068, 10067, 10066,
    10065, 10064, 10063, 10062,
    10061, 10060, 10059, 10058, 10057, 10056,
    10055, 10054, 10053, 10052, 10051, 10050, 10049, 10048, 10047, 10046, 10045, 10044, 10043, 10042,
    10041, 10040, 10039, 10038, 10037, 10036, 10035, 10034, 10033, 10032, 10031, 10030, 10029, 10028,
    10027, 10026, 10025, 10024, 10023, 10022, 10021, 10020, 10019, 10018, 10017, 10016, 10015, 10014,
    10013, 10012, 10011, 10010, 10009, 10008, 10007, 10006, 10005, 10004, 10003, 10002, 10001, 10000,
    9999, 9998, 9997, 9996, 9995, 9994, 9993, 9992, 9991, 9990, 9989, 9988, 9987, 9986, 9985, 9984, 9983,
    9982.
    9981, 9980, 9979, 9978, 9977, 9976)
    

    每次您前进一个页面时,此查询都会变得越来越大,这就是性能问题所在。

    我决定坚持使用Illuminate\Support\Collection 并使用数组,查询如下所示:

    select * from `blog_posts` where `user_id` = 1 and (`id` < 9848) order by `id` desc limit 17
    

    这似乎更高效。

    【讨论】:

      【解决方案2】:

      不确定这是否是最佳或最优雅的解决方案,但您可以尝试将数组转换为对象...

      foreach($posts->items() as $post) {
          $this->blogPosts->push(new BlogPost($post));
      }
      

      编辑:哎呀...我认为下面的逻辑更正确。

      foreach($posts->items() as $post) {
          $this->blogPosts->push(BlogPost::find($post->id));
      }
      

      编辑:如果您对为每条记录运行查找查询感觉不好。这种方法可能更快。

      $blog_post_ids = collect($posts->items())->pluck('id')->toArray();
      $blog_posts = BlogPost::whereIn('id', $blog_post_ids)->get();
      $this->blogPosts->push(...$blog_posts);
      

      【讨论】:

      • 这些仍然返回相同的结果。
      • 对不起,我的声誉还不到50,所以无法评论你的回答。所以可以在这个线程中继续讨论。那么它现在工作了吗?我认为我的第三种方法是最理想的一种,应该使用那个,我不确定收集模型问题的差异。
      • $blog_post_ids = collect($posts-&gt;items())-&gt;pluck('id')-&gt;toArray(); $blog_posts = BlogPost::whereIn('id', $blog_post_ids)-&gt;get(); $this-&gt;blogPosts-&gt;push(...$blog_posts);
      • 我无法让它与您的建议一起使用。我尝试了每一个,每次他们返回相同的混合结果。为了解决这个问题,我将 Illuminate\Support\Collection 更改为 Illuminate\Database\Eloquent\Collection
      猜你喜欢
      • 1970-01-01
      • 2017-07-15
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 2012-02-05
      • 1970-01-01
      • 2015-07-02
      相关资源
      最近更新 更多