LoginSignup
1
5

More than 3 years have passed since last update.

[エラー]Method Illuminate\Support\Collection::paginate does not exist.

Last updated at Posted at 2021-04-22

はじめに

この記事はプログラミング初学者による備忘録用の記事であり、また、少しでも他の初学者のお役に立てればと思い書いています。

今回は、Eloquentで取得したテーブルのデータに対してページネーションの設定を試みた際に発生したエラー解決策を共有したいと思います(Qiitaで似たような記事がありそうですが、、、)。

間違いなどがございましたら、ご指摘のほどよろしくお願い致します。

結論(解決策)

/Providers/AppServiceProvider.phpでLengthAwarePaginatorのインスタンスを作成する
下記のように記述すれば、Method Illuminate\Support\Collection::paginate does not exist.を解決できます。

AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Collection; //追記
use Illuminate\Pagination\LengthAwarePaginator; //追記

class AppServiceProvider extends ServiceProvider
{

 //略

    public function boot() //下記内容を追記
    {
        /**
         * Paginate a standard Laravel Collection.
         *
         * @param int $perPage
         * @param int $total
         * @param int $page
         * @param string $pageName
         * @return array
         */
        Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
            $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

            return new LengthAwarePaginator(
                $this->forPage($page, $perPage)->values(),
                $total ?: $this->count(),
                $perPage,
                $page,
                [
                    'path' => LengthAwarePaginator::resolveCurrentPath(),
                    'pageName' => $pageName,
                ]
            );
        });
    }
}

エラー原因

[Error]Method Illuminate\Database\Eloquent\Collection::paginate does not exist.
下記のように、Eloquentで取得したUserテーブルのデータに対してページネーションの設定を試みた際にエラーが発生

class UserController extends Controller

{
    public function show(string $name)
    {
        $user = User::where('name', $name)->first()->load(['articles.user', 'articles.likes', 'articles.tags']);

        $articles = $user->articles->sortByDesc('created_at')->paginate(10);

        return view('users.show', compact('user', 'articles'));
    }

調べてみて分かったこと

どうやらLaravelはEloquentコレクションにページネーションを提供していますが、デフォルトでは使用できないらしい。

ちなみに、コレクションにはforPage()メソッドがありますが、ページネーションリンクは生成されず、私が求めていた機能とは異なるので使用していません。

このような場合、AppServiceProvider.phpでLengthAwarePaginatorのインスタンスを作成する必要があることがわかりました。
Eloquentのコレクションと同じ動作をさせたい場合,結論で述べたコードを記述することで可能になるとのこと。

構文と出力がEloquent Collectionのpaginate()メソッドとほぼ同じなので、テストの際に(比較的)簡単にEloquent Collectionと入れ替えることができるそうです。便利そうですね。

補足1

URLに追加するクエリパラメータを渡す必要がある場合は、下記のようにパラメータの配列を追加することで可能になります。

before
Collection::macro('paginate', function($perPage, $total = null, $page = null, $pageName = 'page') {
//略
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
after
Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page', $queryParams = []//追記) {
//略
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
'query' => $queryParams //追記
]

補足2

今回記述したコードは、基本的に好きな場所に置くことができます。ここでは、AppServiceProvider.phpに入れてエラーを解決していますが、理由としてはほとんどのLaravelアプリケーションがデフォルトでAppServiceProvider.phpが存在しているからです。

参考文献

laravel6.x公式ドキュメント ページネーション

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5