首頁 >後端開發 >php教程 >Laravel的分頁指南

Laravel的分頁指南

Johnathan Smith
Johnathan Smith原創
2025-03-06 02:04:09642瀏覽

分頁是Web應用程序中的常見功能。我從事過的幾乎所有Laravel應用程序都實施了某種形式的分頁。

但是什麼是分頁,為什麼要使用它?我們如何在Laravel應用程序中實施分頁?我們如何決定要使用哪種分頁方法? 在本文中,我們將回答這些問題,並探索如何在Laravel中使用分頁來獲得刀片視圖和API端點。到本文結束時,您應該有足夠的信心開始在自己的項目中使用分頁。

#什麼是分頁?

分頁是一種用於將大數據集分為較小塊(或頁面)的技術。它允許您顯示數據的一個子集,而不是一次顯示所有可能的值。

> 例如,想像一下,您有一個頁面,可以輸出應用程序中所有用戶的名稱。如果您有成千上萬的用戶,則將所有用戶全部顯示在單個頁面上是不切實際的。取而代之的是,您可以使用分頁來在每個頁面上顯示一個用戶的子集(例如10個用戶),並允許用戶在頁面之間導航以查看更多用戶(下一個10)。

通過使用分頁,您可以:>

>提高應用程序的性能 - 由於您一次獲取較小的數據子集,因此您可以從數據庫中獲取的數據更少,然後返回。

改善用戶體驗 - 用戶一次只能一次對一小部分數據感興趣(通常在前幾頁中找到,尤其是在使用過濾器和搜索詞時)。通過使用分頁,您可以避免顯示用戶不感興趣的數據。

>

改進頁面加載時間 - 僅一次獲取數據的子集,您可以減少需要加載到頁面上的數據量,從而可以改善頁面加載和JavaScript處理時間。

>

分頁通常可以分為兩種不同的類型:

>

基於偏移的分頁 - 這是您可能會在Web應用程序中遇到的最常見的分頁類型,尤其是在用戶界面(UI)中。它涉及基於“偏移”和“限制”從數據庫中獲取數據庫的子集。例如,您可能會從第20個記錄開始獲取10個記錄,以獲取數據的第三頁。
    基於光標的分頁 - 這種類型的分頁涉及根據“光標”獲取數據子集。光標通常是數據庫中記錄的唯一標識符。例如,您可以從記錄開始的下一個10個記錄中獲取ID 20的記錄。
  • Laravel提供了三種不同的方法,用於在您的應用程序中使用雄辯的查詢:
    • paginate - 使用基於偏移的分頁並獲取數據集中的記錄總數。 >
    • - 使用基於偏移的分頁,但沒有獲取數據集中的記錄總數。 > simplePaginate
    • - 使用基於光標的分頁,並且不會獲取數據集中的記錄總數。 >
    • cursorPaginate>讓我們更詳細地看一下這些方法。
    • >
    #use

    方法

    paginate方法允許您根據偏移和限制從數據庫中獲取數據子集(當我們查看基礎SQL查詢時,我們將在稍後查看這些數據庫)。

    您可以使用這樣的方法:

    paginate

    >運行上述代碼將導致

    >是paginate的實例,通常是

    >對象。此Paginator實例包含您需要在應用程序中顯示分頁數據的所有信息。 >
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    
    $users = User::query()->paginate();
    

    方法可以根據URL中的$users查詢參數自動確定所請求的頁碼。例如,如果您訪問了IlluminateContractsPaginationLengthAwarePaginatorIlluminatePaginationLengthAwarePaginator方法將獲取數據的第二頁。 默認情況下,Laravel默認情況下的所有分頁方法一次都以一次獲取15個記錄。但是,這可以將其更改為不同的值(我們將稍後再看一下)。

    >

    #usingpaginate帶有刀片視圖page https://my-app.com/users?page=2>讓我們看一下在刀片視圖中呈現數據時如何使用paginate的方法。

    想像我們有一條簡單的路由,可以以分頁格式從數據庫中獲取用戶,並將其傳遞給視圖:

    paginate我們的

    文件可能看起來像這樣:

    > paginate

    結果頁面看起來像這樣:

    >

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('users', function () {
        $users = User::query()->paginate();
    
        return view('users.index', [
            'users' => $users,
        ]);
    });
    

    resources/views/users/index.blade.php

    >讓我們分解刀片視圖中發生的事情:
    <!-- Syntax highlighted by torchlight.dev --><html>
    <head>
        <title>Paginate</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    
    <body>
        <div class="max-w-5xl mx-auto py-8">
            <h1 class="text-5xl">Paginate</h1>
    
            <ul class="py-4">
                @foreach ($users as $user)
                    <li class="py-1 border-b">{{ $user->name }}</li>
                @endforeach
            </ul>
    
            {{ $users->links() }}
        </div>
    </body>
    </html>
    
    • >我們正在循環瀏覽$users字段中存在的每個用戶(IlluminatePaginationLengthAwarePaginator>對象)並輸出其名稱。
    • >
    • >我們在對像上調用links>方法。這是一種非常方便的方法,它返回一些顯示分頁鏈接的HTML(例如“上一個”,“下一個”和頁碼)。這意味著您不必擔心自己創建分頁鏈接,而Laravel會為您處理所有這些。 $users
    >我們還可以看到,

    方法正在為我們提供分頁數據的概述。我們可以看到,我們正在查看第16至30個記錄,總共有50個記錄。我們還可以看到我們在第二頁上,總共有4頁。 paginate>重要的是要注意,

    >方法將使用尾風CSS返回HTML樣式。如果您想使用除尾風以外的其他東西,或者想自己設置分頁鏈接,則可以查看有關自定義分頁視圖的文檔。

    > links #using

    在API端點

    paginate以及在刀片視圖中使用

    方法,您也可以在API端點中使用它。 Laravel通過將分頁的數據自動轉換為JSON,使此過程變得容易。 端點(通過將以下路由添加到我們的paginate文件),該端口以JSON格式返回了分頁的用戶:>

    >訪問/api/users端點將返回類似於以下的JSON響應(請注意,出於簡潔起見,我將routes/api.php>字段限制為3個記錄):>

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    
    $users = User::query()->paginate();
    
    讓我們分解JSON響應:

    • current_page - 我們正在使用的當前頁面。在這種情況下,我們在第一頁上。
    • data - 正在返回的實際數據本身。在這種情況下,它包含前15位用戶(簡短為3個用戶)。
    • >
    • first_page_url - 數據的第一頁的URL。
    • >
    • from - 返回數據的起始記錄號。在這種情況下,這是第一個記錄。如果我們在第二頁上,那將是16。
    • - 數據的總數。在這種情況下,有4頁。 last_page
    • - 數據的最後一頁的URL。 last_page_url>
    • - 指向數據不同頁面的鏈接數組。這包括“上一個”和“下一個”鏈接以及頁碼。 links>
    • - 數據的下一頁的URL。 next_page_url
    • - 端點的基本URL。
    • > path
    • - 每頁返回的記錄數。在這種情況下,是15。
    • per_page - 數據的上一頁的URL。在這種情況下,這是
    • ,因為我們在第一頁上。如果我們在第二頁上,這將是第一頁的URL。
    • > prev_page_urlnull - 返回數據的結尾記錄號。在這種情況下,這是第15張記錄。如果我們在第二頁上,那將是30。
    • - 數據集中的記錄總數。在這種情況下,有50個記錄。 to
    • #基礎SQL查詢total
    • 在Laravel中使用
    方法會導致兩個SQL查詢正在運行:

    第一個查詢獲取數據集中的記錄總數。這用於確定信息,例如頁面總數和記錄總數。 paginate第二個查詢根據偏移和限制值獲取數據子集。例如,它可能正在獲取用戶以供我們處理和返回。

    >
    • >因此,如果我們想獲取用戶的第一頁(每個頁面有15個用戶),則將運行以下SQL查詢:
    • >

    在第二個查詢中,我們可以看到
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    
    $users = User::query()->paginate();
    
    值設置為15。這是每頁返回的記錄數。

    >

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('users', function () {
        $users = User::query()->paginate();
    
        return view('users.index', [
            'users' => $users,
        ]);
    });
    
    值的計算如下:

    > limit

    >因此,如果我們想獲取用戶的第三頁,則

    的值將計算為:offset>

    <!-- Syntax highlighted by torchlight.dev --><html>
    <head>
        <title>Paginate</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    
    <body>
        <div class="max-w-5xl mx-auto py-8">
            <h1 class="text-5xl">Paginate</h1>
    
            <ul class="py-4">
                @foreach ($users as $user)
                    <li class="py-1 border-b">{{ $user->name }}</li>
                @endforeach
            </ul>
    
            {{ $users->links() }}
        </div>
    </body>
    </html>
    
    >因此,

    值將為30,我們將獲取第31到第45個記錄。第三頁的查詢看起來像:offset

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('paginate', function () {
        return User::query()->paginate();
    });
    

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    
    $users = User::query()->paginate();
    

    #use simplePaginate方法

    simplePaginate方法與paginate方法非常相似,但具有一個關鍵差異。該方法未獲取數據集中的記錄總數。 simplePaginate> 正如我們剛剛看到的那樣,當我們使用

    方法時,我們還會獲取有關數據集中可用的記錄總數和頁面的信息。然後,我們可以使用此信息來顯示諸如UI或API響應中的頁面總數等內容。

    > paginate>但是,如果您不打算向用戶(或消耗API的開發人員)顯示這些詳細信息,那麼我們可以使用

    >

    >simplePaginate>來避免不需要的數據庫查詢(計算記錄總數)。

    方法可以與simplePaginate方法相同的方式使用:paginate>

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('users', function () {
        $users = User::query()->paginate();
    
        return view('users.index', [
            'users' => $users,
        ]);
    });
    
    運行上述代碼將導致

    的實例,通常為$users>對象。 IlluminateContractsPaginationPaginator>與IlluminatePaginationPaginator方法返回的對像不同,

    >對像不包含有關數據集中記錄總數的信息,也不知道有多少頁或總記錄。它只知道當前數據頁面以及是否還有更多記錄可以獲取。

    > IlluminatePaginationLengthAwarePaginator #usingpaginate帶有刀片視圖IlluminatePaginationPaginator

    >讓我們看一下如何使用刀片視圖的方法。我們假設我們有與以前相同的路線,但是這次我們使用的

    方法:> simplePaginate

    我們將以與以前相同的方式構建刀片視圖:

    > simplePaginate simplePaginate結果頁面看起來像這樣:

    >
    <!-- Syntax highlighted by torchlight.dev --><html>
    <head>
        <title>Paginate</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    
    <body>
        <div class="max-w-5xl mx-auto py-8">
            <h1 class="text-5xl">Paginate</h1>
    
            <ul class="py-4">
                @foreach ($users as $user)
                    <li class="py-1 border-b">{{ $user->name }}</li>
                @endforeach
            </ul>
    
            {{ $users->links() }}
        </div>
    </body>
    </html>
    

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('paginate', function () {
        return User::query()->paginate();
    });
    
    正如我們在此示例中所看到的那樣,

    >的輸出與使用

    >方法時看到的輸出不同。由於該方法沒有獲取記錄總數,因此它沒有頁面或記錄總數的上下文,只有下一頁是否存在。因此,我們僅在分頁鏈接中看到“上一個”和“下一個”鏈接。

    > #using在API端點

    >您也可以在API端點中使用$users->links()>方法。 Laravel將自動將分頁數據轉換為您的JSON。 paginate>讓我們構建一個simplePaginate端點,以JSON格式返回分頁的用戶:

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    
    $users = User::query()->paginate();
    

    >當我們碰到這條路線時,我們將獲得類似於以下內容的JSON響應(我將data>字段限制為僅3個記錄的簡短):

    >
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('users', function () {
        $users = User::query()->paginate();
    
        return view('users.index', [
            'users' => $users,
        ]);
    });
    
    如我們所見,JSON響應與使用

    >方法時得到的響應非常相似。關鍵區別在於,我們沒有響應中的paginatelast_pagelast_page_url>字段。 linkstotal#基礎SQL查詢

    >讓我們看一下使用

    >方法時運行的基礎SQL查詢。

    simplePaginate

    方法仍然依賴於

    simplePaginate>值來獲取數據庫的數據子集。但是,它沒有運行查詢來獲取數據集中的記錄總數。 > limitoffset值仍以與以前相同的方式計算:

    >

    但是,offset值的計算略有不同。它被計算為:

    <!-- Syntax highlighted by torchlight.dev --><html>
    <head>
        <title>Paginate</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    
    <body>
        <div class="max-w-5xl mx-auto py-8">
            <h1 class="text-5xl">Paginate</h1>
    
            <ul class="py-4">
                @foreach ($users as $user)
                    <li class="py-1 border-b">{{ $user->name }}</li>
                @endforeach
            </ul>
    
            {{ $users->links() }}
        </div>
    </body>
    </html>
    

    這是因為limit>方法需要比paginate值更多的記錄來確定是否有更多記錄可以獲取。例如,假設我們每頁獲取15個記錄。

    >值將為16。因此,如果要返回16個記錄,我們知道至少還有一頁可以獲取的數據。如果返回了少於16個記錄,我們會知道我們在數據的最後一頁。
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('paginate', function () {
        return User::query()->paginate();
    });
    
    >因此,如果我們想獲取用戶的第一頁(每個頁面有15個用戶),則將運行以下SQL查詢:

    > simplePaginate perPage第二頁的查詢看起來像:limit

    #use

    方法
    <!-- Syntax highlighted by torchlight.dev -->{
      "current_page": 1,
      "data": [
        {
          "id": 1,
          "name": "Andy Runolfsson",
          "email": "teresa.wiegand@example.net",
          "email_verified_at": "2024-10-15T23:19:28.000000Z",
          "created_at": "2024-10-15T23:19:29.000000Z",
          "updated_at": "2024-10-15T23:19:29.000000Z"
        },
        {
          "id": 2,
          "name": "Rafael Cummings",
          "email": "odessa54@example.org",
          "email_verified_at": "2024-10-15T23:19:28.000000Z",
          "created_at": "2024-10-15T23:19:29.000000Z",
          "updated_at": "2024-10-15T23:19:29.000000Z"
        },
        {
          "id": 3,
          "name": "Reynold Lindgren",
          "email": "juwan.johns@example.net",
          "email_verified_at": "2024-10-15T23:19:28.000000Z",
          "created_at": "2024-10-15T23:19:29.000000Z",
          "updated_at": "2024-10-15T23:19:29.000000Z"
        }
      ],
      "first_page_url": "http://example.com/users?page=1",
      "from": 1,
      "last_page": 4,
      "last_page_url": "http://example.com/users?page=4",
      "links": [
        {
          "url": null,
          "label": "&laquo; Previous",
          "active": false
        },
        {
          "url": "http://example.com/users?page=1",
          "label": "1",
          "active": true
        },
        {
          "url": "http://example.com/users?page=2",
          "label": "2",
          "active": false
        },
        {
          "url": "http://example.com/users?page=3",
          "label": "3",
          "active": false
        },
        {
          "url": "http://example.com/users?page=4",
          "label": "4",
          "active": false
        },
        {
          "url": "http://example.com/users?page=5",
          "label": "5",
          "active": false
        },
        {
          "url": "http://example.com/users?page=2",
          "label": "Next &raquo;",
          "active": false
        }
      ],
      "next_page_url": "http://example.com/users?page=2",
      "path": "http://example.com/users",
      "per_page": 15,
      "prev_page_url": null,
      "to": 15,
      "total": 50
    }
    
    到目前為止,我們已經研究了

    >和

    的方法,這些方法都使用了基於偏移的分頁。現在,我們將查看使用基於光標的分頁的
    <!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
    
    >方法。

    > cursorPaginate作為一個頭部,基於光標的分頁似乎有些混亂,當您第一次遇到它時。因此,如果您不立即將其拿走,請不要擔心。希望在本文結尾,您將對它的工作原理有了更好的了解。我還將在本文的末尾留下一個很棒的視頻,該視頻更詳細地解釋了基於光標的分頁。

    >

    >使用基於偏移的分頁,我們使用paginatesimplePaginate>值從數據庫中獲取數據子集。因此,我們可以說“跳過前10個記錄並獲取接下來的10個記錄”。這很容易理解且易於實現。儘管使用光標分頁,我們使用光標(通常是數據庫中特定記錄的唯一標識符)作為獲取上一組/下一組記錄的起點。例如,假設我們要查詢以獲取前15個用戶。我們假設第15個用戶的ID為20。當我們要獲取接下來的15個用戶時,我們將使用第15用戶(20)的ID作為光標。我們將說“獲取接下來的15個用戶,ID大於20”。

    >

    >您有時可能會看到光標稱為“令牌”,“鍵”,“下一步”,“上一個”等。它們本質上是對數據庫中特定記錄的參考。當我們查看基礎SQL查詢時,我們將在本節中稍後查看光標的結構。

    laravel允許我們輕鬆地使用基於光標的分頁來使用

    >:> cursorPaginate

    >運行上述代碼將導致字段是<!-- Syntax highlighted by torchlight.dev -->use App\Models\User; $users = User::query()->paginate(); >對象。此Paginator實例包含您需要在應用程序中顯示分頁數據的所有信息。 >

    >類似於$users>方法,該方法不會獲取數據集中的記錄總數。它僅知道當前數據頁面以及是否還有更多記錄需要獲取,因此我們不立即意識到頁面或記錄的總數。 IlluminateContractsPaginationCursorPaginator> IlluminatePaginationCursorPaginator #using

    帶有刀片視圖

    simplePaginate>讓我們看一下如何在刀片視圖中呈現數據時如何使用cursorPaginate的方法。與我們以前的示例類似,我們假設我們有一條簡單的路由,可以以分頁的格式從數據庫中獲取用戶,並將其傳遞給視圖:

    cursorPaginate刀片視圖可能看起來像這樣:

    cursorPaginate這將輸出一個類似於以下幾個頁面:

    >
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('users', function () {
        $users = User::query()->paginate();
    
        return view('users.index', [
            'users' => $users,
        ]);
    });
    

    <!-- Syntax highlighted by torchlight.dev --><html>
    <head>
        <title>Paginate</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    
    <body>
        <div class="max-w-5xl mx-auto py-8">
            <h1 class="text-5xl">Paginate</h1>
    
            <ul class="py-4">
                @foreach ($users as $user)
                    <li class="py-1 border-b">{{ $user->name }}</li>
                @endforeach
            </ul>
    
            {{ $users->links() }}
        </div>
    </body>
    </html>
    
    正如我們所能看到的,由於

    方法沒有獲取數據集中的記錄總數,因此的輸出與使用

    >方法時看到的輸出相似。我們僅在分頁鏈接中看到“上一個”和“下一個”鏈接。

    #using在API端點中

    laravel還允許您在API端點中使用

    >方法,並將自動將頁上的數據轉換為我們的JSON。 cursorPaginate>讓我們構建一個$users->links()端點,以JSON格式返回分頁的用戶:simplePaginate

    >當我們碰到這條路線時,我們將獲得類似於以下內容的JSON響應(我將cursorPaginate>字段限制為僅3個記錄的簡短):

    >
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    
    $users = User::query()->paginate();
    
    如我們所見,JSON響應類似於我們看到的先前響應,但差異很小。由於我們沒有獲取記錄的總數,因此我們沒有響應中的

    字段。您可能還注意到我們也沒有last_pagelast_page_url>字段。 links> 相反,我們有total>和from>字段,該字段包含數據的下一個和上一個數據頁面的光標。由於我們在第一頁上,因此to

    字段均為

    >。但是,設置了next_cursorprev_cursor字段。 prev_cursor> prev_page_urlnull字段是一個基本-64編碼的字符串,其中包含數據的下一頁的光標。如果我們解碼next_cursor>字段,我們會得到這樣的東西(為可讀性而美化):> next_page_url

    光標包含兩個單獨的信息:

    next_cursor next_cursor

    - 數據集中獲取的最後一個記錄的ID。
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('users', function () {
        $users = User::query()->paginate();
    
        return view('users.index', [
            'users' => $users,
        ]);
    });
    
    >

    - 一個布爾值告訴我們光標是指向下一組還是上一組項目。如果值為
      >,則意味著光標應用於獲取ID大於
    • >值的下一組記錄。如果該值為users.id,則意味著光標應用於以ID小於
    • value的ID進行以下記錄集。 >。
    • _pointsToNextItems>讓我們看一下數據的第二頁可能是什麼樣子(再次縮短到3個記錄,以簡化):true users.id false我們可以看到現在設置了users.id
    • >字段,並且已使用光標更新了數據的下一頁。
    #基礎SQL查詢

    為了更好地了解光標分頁在引擎蓋下的工作方式,讓我們看一下使用
    <!-- Syntax highlighted by torchlight.dev --><html>
    <head>
        <title>Paginate</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    
    <body>
        <div class="max-w-5xl mx-auto py-8">
            <h1 class="text-5xl">Paginate</h1>
    
            <ul class="py-4">
                @foreach ($users as $user)
                    <li class="py-1 border-b">{{ $user->name }}</li>
                @endforeach
            </ul>
    
            {{ $users->links() }}
        </div>
    </body>
    </html>
    
    >方法時運行的基礎SQL查詢。 在數據的第一頁上(包含15個記錄),將運行以下SQL查詢:>

    prev_cursor>我們可以看到,我們正在從prev_page_url>表中獲取前16個記錄,並按next_cursor列以升序順序訂購。與next_page_url方法相似,我們要提取16行,因為我們想確定是否還有更多記錄可以獲取。

    >

    >讓我們想像我們然後通過以下光標導航到項目的下一頁:>

    當該光標被解碼時,我們會得到以下JSON對象: cursorPaginate 然後,Laravel將運行以下SQL查詢以獲取下一組記錄:>

    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    
    $users = User::query()->paginate();
    
    如我們所見,我們從

    >表中獲取了下一16個記錄,該記錄大於15(因為15是上一頁的最後一個ID)。 users現在,讓我們假設第2頁上的第一個用戶的ID是16。當我們從第二頁導航回數據的第一頁時,將使用以下光標: id

    解碼時,我們將獲得以下JSON對象:

    >當我們轉到結果的下一頁時,獲取的最後一個記錄被用作光標。當我們返回結果的上一頁時,獲取的第一個記錄被用作光標。因此,我們可以看到在光標中設置為16。我們還可以看到
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('users', function () {
        $users = User::query()->paginate();
    
        return view('users.index', [
            'users' => $users,
        ]);
    });
    
    >值設置為

    ,因為我們正在回到先前的項目。

    。 結果,將運行以下SQL查詢以獲取先前的記錄集:>
    <!-- Syntax highlighted by torchlight.dev --><html>
    <head>
        <title>Paginate</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    
    <body>
        <div class="max-w-5xl mx-auto py-8">
            <h1 class="text-5xl">Paginate</h1>
    
            <ul class="py-4">
                @foreach ($users as $user)
                    <li class="py-1 border-b">{{ $user->name }}</li>
                @endforeach
            </ul>
    
            {{ $users->links() }}
        </div>
    </body>
    </html>
    

    >正如我們所看到的,users.id約束現在正在檢查_pointsToNextItems少於16的記錄(因為第2頁上的第一個ID是16個),並且結果以降序排序。 false#使用分頁的API資源

    到目前為止,在我們的API示例中,我們剛剛直接從控制器返回了分頁數據。但是,在現實世界中,您可能需要在將數據返回給用戶之前處理。這可能是從添加或刪除字段,轉換數據類型甚至將數據完全轉換為不同格式的任何方法。因此,您可能需要使用API​​資源,因為它們為您提供了一種在返回數據之前始終轉換數據的方法。

    Laravel

    允許您在分頁上使用API​​資源。讓我們看一個如何做的示例。
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('paginate', function () {
        return User::query()->paginate();
    });
    
    >

    想像我們已經創建了一個API資源類,該類別在返回之前會轉換用戶數據。它看起來像這樣:where id

    >在

    >方法中,我們定義,每當我們通過此資源處理用戶時,我們只想返回

    >,

    > fields。

    現在,讓我們在我們的

    >文件中構建一個簡單的API端點,該文件使用

    AppHttpResourcesUserResource返回了分頁的用戶

    <!-- Syntax highlighted by torchlight.dev -->{
      "current_page": 1,
      "data": [
        {
          "id": 1,
          "name": "Andy Runolfsson",
          "email": "teresa.wiegand@example.net",
          "email_verified_at": "2024-10-15T23:19:28.000000Z",
          "created_at": "2024-10-15T23:19:29.000000Z",
          "updated_at": "2024-10-15T23:19:29.000000Z"
        },
        {
          "id": 2,
          "name": "Rafael Cummings",
          "email": "odessa54@example.org",
          "email_verified_at": "2024-10-15T23:19:28.000000Z",
          "created_at": "2024-10-15T23:19:29.000000Z",
          "updated_at": "2024-10-15T23:19:29.000000Z"
        },
        {
          "id": 3,
          "name": "Reynold Lindgren",
          "email": "juwan.johns@example.net",
          "email_verified_at": "2024-10-15T23:19:28.000000Z",
          "created_at": "2024-10-15T23:19:29.000000Z",
          "updated_at": "2024-10-15T23:19:29.000000Z"
        }
      ],
      "first_page_url": "http://example.com/users?page=1",
      "from": 1,
      "last_page": 4,
      "last_page_url": "http://example.com/users?page=4",
      "links": [
        {
          "url": null,
          "label": "&laquo; Previous",
          "active": false
        },
        {
          "url": "http://example.com/users?page=1",
          "label": "1",
          "active": true
        },
        {
          "url": "http://example.com/users?page=2",
          "label": "2",
          "active": false
        },
        {
          "url": "http://example.com/users?page=3",
          "label": "3",
          "active": false
        },
        {
          "url": "http://example.com/users?page=4",
          "label": "4",
          "active": false
        },
        {
          "url": "http://example.com/users?page=5",
          "label": "5",
          "active": false
        },
        {
          "url": "http://example.com/users?page=2",
          "label": "Next &raquo;",
          "active": false
        }
      ],
      "next_page_url": "http://example.com/users?page=2",
      "path": "http://example.com/users",
      "per_page": 15,
      "prev_page_url": null,
      "to": 15,
      "total": 50
    }
    
    >在上面的代碼中,我們從數據庫中獲取了一個用戶(假設它是包含15個用戶的第一頁)的單個頁面。然後,我們將

    字段(將是toArray>的實例)傳遞給id>方法。此方法將在將其退還給用戶之前使用name轉換分頁的數據。

    >當我們擊中/api/users端點時,我們將獲得類似於以下內容的JSON響應(我將data>字段限制為僅3個記錄的簡短記錄):

    >
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    
    $users = User::query()->paginate();
    
    正如我們在上面的JSON中看到的那樣,Laravel檢測到我們正在使用分頁數據集,並以與以前相似的格式返回分頁數據。但是,這一次,

    >字段中的用戶僅包含我們在API資源類中指定的data>,idname>字段。其他字段(emailcurrent_pagefromlast_pagelinkspathper_pagetototal)仍被返回,因為它們是分頁數據的一部分,但它們已放置在meta>字段中。還有一個包含linksfirstlast的字段,prev>鏈接到數據的不同頁面。 next #Changing每個頁面值

    >使用分頁數據構建視圖時,您可能需要允許用戶更改每個頁面顯示的記錄數量。這可能是通過下拉列表或數字輸入字段。

    > Laravel使通過將A

    >參數傳遞到

    >,

    perPage>方法來更改每個頁面顯示的記錄數量變得容易。此參數允許您指定要顯示每個頁面的記錄數。 simplePaginate> paginate>讓我們看一個簡單的示例,說明如何讀取acursorPaginate查詢參數並使用它來更改每頁獲取的記錄數量:

    per_page在上面的示例中,我們正在抓取

    QUERY參數的值。如果未提供該值,我們將默認為10。然後,我們將該值傳遞給
    <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
    use Illuminate\Support\Facades\Route;
    
    Route::get('users', function () {
        $users = User::query()->paginate();
    
        return view('users.index', [
            'users' => $users,
        ]);
    });
    
    >方法的

    參數。 然後,我們可以訪問這些不同的URL:> per_page perPagepaginate - 顯示用戶的第一頁,每頁10個記錄。 >

    - 顯示用戶的首頁,每頁5個記錄。 >

      - 顯示用戶的第二頁,每頁5個記錄。 >
    • 等等...https://my-app.com/users
    • #如何決定要使用哪種分頁方法https://my-app.com/users?per_page=5
    • >現在我們已經研究了分頁的不同類型以及如何在Laravel中使用它們,我們將討論如何確定在您的應用程序中使用的哪種方法。 >
    • #do您需要頁碼或記錄總數? https://my-app.com/users?per_page=5&page=2>
    • 如果您要構建需要顯示的記錄或頁面總數或頁面的UI或API端點,則
    • >方法可能是一個明智的選擇。
    • >

      如果您不需要任何一個,則simplePaginatecursorPaginate將會更有效,因為它們沒有執行不必要的查詢來計算記錄總數。 >

      #do您需要跳到特定頁面?

      >

      如果您需要能夠跳到特定的數據頁面,則基於偏移的分頁更合適。由於光標分頁是有狀態的,因此它依靠上一頁知道下一步要去哪裡。因此,跳到特定頁面並不容易。

      >

      >使用偏移分頁時,您通常只需傳遞請求中的頁碼(也許作為查詢參數),然後跳到該頁面而不具有上一頁的任何上下文。

      #wath是多大的數據集?

      >

      由於數據庫處理

      >值的方式,基於偏移的分頁隨著頁碼的增加而變得效率降低。這是因為當您使用偏移量時,數據庫仍然必須掃描所有記錄,直至偏移值。他們只是被丟棄,在查詢結果中沒有返回。

      > offset這是一篇很棒的文章,可以更詳細地解釋這一點:https://use-the-index-luke.com/no-offset。

      因此,隨著數據庫中數據總數的增長和頁數增加,基於偏移的分頁的效率也降低了。在這些情況下,基於光標的分頁的性能更高,尤其是在索引光標字段的情況下,因為先前的記錄未讀取。因此,如果您要針對大型數據集使用分頁,您可能需要選擇光標分頁而不是偏移分頁。

      #是可能經常更改的數據集嗎?

      如果請求之間的基礎數據集更改,則基於偏移的分頁可能會遇到問題。

      讓我們來看看一個例子。

      是說我們數據庫中有以下10個用戶:

      >

      用戶1

      用戶2
      • 用戶3
      • 用戶4
      • >用戶5
      • 用戶6
      • 用戶7
      • 用戶8
      • >用戶9
      • 用戶10
      • 我們提出請求獲取第一頁(包含5個用戶)並獲取以下用戶:>
      • 用戶1

      用戶2

        用戶3
      • 用戶4
      • >用戶5
      • >當我們導航到第2頁時,我們希望將用戶6到10。但是,讓我們想像,在加載第2頁之前(當我們仍在查看第1頁時),從數據庫中刪除了用戶1。由於頁面大小為5,因此獲取下一頁的查詢看起來像:
      • >
      • 這意味著我們要跳過前5個記錄並獲取下一個5.
      這將導致包含以下用戶的第2頁:

      <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
      
      $users = User::query()->paginate();
      
      用戶7

      用戶8

      >用戶9
      • 用戶10
      • 正如我們所看到的,列表中缺少用戶6。這是因為用戶6現在是表中的第五個記錄,因此它們實際上是在第一頁上。
      • >基於光標的分頁沒有這個問題,因為我們沒有跳過記錄,我們只是根據光標獲取下一組記錄。讓我們想像我們在上面的示例中使用了基於光標的分頁。第2頁的光標將是用戶5的ID(我們假設為5),因為它是首頁上的最後一個記錄。因此,我們對第2頁的查詢可能看起來像這樣:

        <!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
        
        $users = User::query()->paginate();
        
        運行上述查詢將按預期返回6至10的用戶。

        >

        >這應該有望突出顯示基於偏移的分頁如何在讀取基礎數據,添加或刪除的基礎數據時如何成為問題。它變得不可預測,並可能導致意外的結果。

        >

        #您要構建API?

        >

        >重要的是要記住,您沒有固定在應用程序中使用單一類型的分頁。在某些地方,偏移分頁可能更合適(也許是為了UI目的),而在其他地方,光標分頁可能更有效(例如,使用大型數據集時)。因此,您可以根據用例中的應用程序混合和匹配分頁方法。

        > 但是,如果您要構建API,我強烈建議您保持一致,並為所有端點使用單個分頁方法。這將使開發人員更容易理解如何使用API​​並避免任何混亂。 >

        >您不希望他們記住哪些端點使用偏移 - 流動以及哪些端點使用光標 -

        當然,這不是一個艱難而快速的規則。如果您確實需要在一個特定端點中使用其他分頁方法,請繼續。但是,只要確保在文檔中清楚地表明它,以使開發人員更容易理解。

        #prefer視頻?

        >

        >如果您更像是一個視覺學習者,則可能需要查看Aaron Francis的這個很棒的視頻,該視頻會更詳細地解釋基於偏移和基於Cursor的分頁之間的區別:>

        #conclusion

        在本文中,我們研究了Laravel中不同類型的分頁以及如何使用它們。我們還研究了他們的基礎SQL查詢以及如何確定在您的應用程序中使用的分頁方法。 希望您現在應該更有信心在Laravel應用程序中使用分頁。

以上是Laravel的分頁指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn