Maison > développement back-end > tutoriel php > Un guide de la pagination à Laravel

Un guide de la pagination à Laravel

Johnathan Smith
Libérer: 2025-03-06 02:04:09
original
633 Les gens l'ont consulté

La pagination est une caractéristique commune dans les applications Web. Presque toutes les applications Laravel sur lesquelles j'ai travaillé ont eu une certaine forme de pagination implémentée.

Mais qu'est-ce que la pagination et pourquoi l'utiliser? Comment pouvons-nous mettre en œuvre une pagination dans nos applications Laravel? Et comment décidons-nous de quelle méthode de pagination utiliser?

Dans cet article, nous allons répondre à ces mêmes questions et explorer comment utiliser la pagination dans Laravel pour les vues de lame et les points de terminaison de l'API. À la fin de cet article, vous devriez vous sentir suffisamment confiant pour commencer à utiliser la pagination dans vos propres projets.

# Qu'est-ce que la pagination?

La pagination est une technique utilisée pour diviser un grand ensemble de données en morceaux (ou pages) plus petits. Il vous permet d'afficher un sous-ensemble des données, plutôt que toutes les valeurs possibles à la fois.

Par exemple, imaginez que vous aviez une page qui publie les noms de tous les utilisateurs de votre application. Si vous aviez des milliers d'utilisateurs, il ne serait pas pratique de les afficher tous sur une seule page. Au lieu de cela, vous pouvez utiliser une pagination pour afficher un sous-ensemble des utilisateurs (disons 10 utilisateurs à la fois) sur chaque page et permettre aux utilisateurs de naviguer entre les pages pour afficher plus d'utilisateurs (les 10 suivants).

En utilisant la pagination, vous pouvez:

  • Améliorez les performances de votre application - puisque vous récupérez un sous-ensemble de données plus petit à la fois, il y a moins de données pour que vous puissiez récupérer à partir de la base de données, processus / transformée, puis retour.
  • Améliorer l'expérience utilisateur - il est probable que l'utilisateur ne sera jamais intéressé par un petit sous-ensemble des données à la fois (généralement trouvé dans les premières pages, surtout si les filtres et les termes de recherche sont utilisés). En utilisant la pagination, vous pouvez éviter d'afficher des données qui ne sont pas intéressées.
  • Améliorer les temps de chargement de la page - en récupérant uniquement un sous-ensemble des données à la fois, vous pouvez réduire la quantité de données qui doivent être chargées sur la page, ce qui peut améliorer le chargement de la page et les temps de traitement JavaScript.

La pagination peut généralement être divisée en deux types différents:

  • Pagination basée sur le décalage - C'est le type de pagination le plus courant que vous rencontrerez probablement dans vos applications Web, en particulier dans les interfaces utilisateur (UI). Il s'agit de récupérer un sous-ensemble de données de la base de données basée sur un "décalage" et une "limite". Par exemple, vous pouvez récupérer 10 enregistrements à partir du 20e enregistrement pour récupérer la 3e page des données.
  • Pagination basée sur le curseur - Ce type de pagination consiste à récupérer un sous-ensemble de données basé sur un "curseur". Le curseur est généralement un identifiant unique pour un enregistrement dans la base de données. Par exemple, vous pouvez récupérer les 10 prochains enregistrements à partir de l'enregistrement avec un ID de 20.

Laravel fournit trois méthodes différentes pour paginir des requêtes éloquentes dans vos applications:

  • paginate - utilise une pagination basée sur le décalage et récupére le nombre total d'enregistrements dans l'ensemble de données.
  • simplePaginate - utilise une pagination basée sur le décalage mais ne va pas le nombre total d'enregistrements dans l'ensemble de données.
  • cursorPaginate - utilise une pagination basée sur le curseur et ne va pas récupérer le nombre total d'enregistrements dans l'ensemble de données.

Jetons un coup d'œil à chacune de ces méthodes plus en détail.

#Using the paginate Method

La méthode paginate vous permet de récupérer un sous-ensemble de données de la base de données en fonction d'un décalage et d'une limite (nous allons les jeter un œil plus tard lorsque nous examinerons les requêtes SQL sous-jacentes).

Vous pouvez utiliser la méthode paginate comme ainsi:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Exécuter le code ci-dessus entraînerait la $users d'être une instance de IlluminateContractsPaginationLengthAwarePaginator, généralement un objet IlluminatePaginationLengthAwarePaginator. Cette instance de paginateur contient toutes les informations dont vous avez besoin pour afficher les données paginées dans votre application.

La méthode paginate peut déterminer automatiquement le numéro de page demandé en fonction du paramètre de requête page dans l'URL. Par exemple, si vous visitez https://my-app.com/users?page=2, la méthode paginate rapporterait la deuxième page des données.

Par défaut, toutes les méthodes de pagination de Laravel par défaut par défaut pour récupérer 15 enregistrements à la fois. Cependant, cela peut être changé à une valeur différente (nous allons voir comment le faire plus tard).

#Using paginate avec vues de lame

Voyons comment utiliser la méthode paginate lors de la rendu des données dans une vue de lame.

Imaginez que nous avons un itinéraire simple qui récupère les utilisateurs de la base de données dans un format paginé et les transmet à une vue:

<!-- 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Notre fichier resources/views/users/index.blade.php peut ressembler à ceci:

<!-- 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>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La page résultante ressemblerait à ceci:

Décomposons ce qui se passe dans la vue de la lame:

  • Nous parcourons chaque utilisateur qui est présent dans le champ $users (l'objet IlluminatePaginationLengthAwarePaginator) et la sortie de son nom.
  • Nous appelons la méthode links sur l'objet $users. Il s'agit d'une méthode vraiment pratique qui renvoie un HTML qui affiche les liens de pagination (par exemple, "précédent", "suivant" et les numéros de page). Cela signifie que vous n'avez pas à vous soucier de créer vous-même les liens de pagination, et Laravel gérera tout cela pour vous.

Nous pouvons également voir que la méthode paginate nous donne un aperçu des données de pagination. Nous pouvons voir que nous regardons les 16e à 30e records, sur un total de 50 enregistrements. Nous pouvons également voir que nous sommes sur la deuxième page et qu'il y a un total de 4 pages.

Il est important de noter que la méthode links renverra le style HTML à l'aide de CSS de vent arrière. Si vous souhaitez utiliser autre chose que le vent arrière ou si vous souhaitez styliser les liens de pagination vous-même, vous pouvez consulter la documentation sur la personnalisation des vues de pagination.

#Using paginate dans les points de terminaison de l'API

ainsi que l'utilisation de la méthode paginate dans les vues de lame, vous pouvez également l'utiliser dans les points de terminaison de l'API. Laravel facilite ce processus en convertissant automatiquement les données paginées en JSON.

Par exemple, nous pourrions créer un point de terminaison /api/users (en ajoutant la route suivante à notre fichier routes/api.php) qui renvoie les utilisateurs paginés au format JSON:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

L'accès au point de terminaison /api/users renverrait une réponse JSON similaire à ce qui suit (veuillez noter que j'ai limité le champ data à seulement 3 enregistrements pour le plaisir de Brivity):

<!-- 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

décomposons la réponse JSON:

  • current_page - La page actuelle sur laquelle nous sommes. Dans ce cas, nous sommes sur la première page.
  • data - Les données réelles elle-même sont renvoyées. Dans ce cas, il contient les 15 premiers utilisateurs (raccourcis à 3 pour Brivity).
  • first_page_url - L'URL à la première page des données.
  • from - Le numéro d'enregistrement de départ des données renvoyé. Dans ce cas, c'est le premier record. Si nous étions sur la deuxième page, ce serait 16.
  • last_page - Le nombre total de pages de données. Dans ce cas, il y a 4 pages.
  • last_page_url - L'URL de la dernière page des données.
  • links - Un tableau de liens vers les différentes pages de données. Cela inclut les liens "précédents" et "suivants", ainsi que les numéros de page.
  • next_page_url - L'URL à la page suivante des données.
  • path - L'URL de base du point de terminaison.
  • per_page - Le nombre d'enregistrements étant retourné par page. Dans ce cas, il est 15.
  • prev_page_url - L'URL à la page précédente des données. Dans ce cas, c'est null parce que nous sommes sur la première page. Si nous étions sur la deuxième page, ce serait l'URL de la première page.
  • to - Le numéro d'enregistrement de fin des données en cours de retour. Dans ce cas, c'est le 15e record. Si nous étions sur la deuxième page, ce serait 30.
  • total - Le nombre total d'enregistrements dans l'ensemble de données. Dans ce cas, il y a 50 enregistrements.

#Les requêtes SQL sous-jacentes

L'utilisation de la méthode paginate dans Laravel Résultats en cours d'exécution de deux requêtes SQL:

  • La première requête récupère le nombre total d'enregistrements dans l'ensemble de données. Ceci est utilisé pour déterminer des informations telles que le nombre total de pages et le nombre total d'enregistrements.
  • La deuxième requête récupère le sous-ensemble de données en fonction du décalage et des valeurs limites. Par exemple, il pourrait être de récupérer les utilisateurs pour que nous puissions traiter et revenir.

Donc, si nous voulions récupérer la première page d'utilisateurs (avec 15 utilisateurs par page), les requêtes SQL suivantes seraient exécutées:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

et

<!-- 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans la deuxième requête, nous pouvons voir que la valeur limit est définie sur 15. Il s'agit du nombre d'enregistrements qui sont retournés par page.

La valeur offset est calculée comme suit:

<!-- 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>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Donc, si nous voulions récupérer la troisième page des utilisateurs, la valeur offset serait calculée comme suit:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('paginate', function () {
    return User::query()->paginate();
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Par conséquent, la valeur offset serait de 30 et nous récupérerions les 31 à 45e enregistrements. Les requêtes de la troisième page ressembleraient à:

<!-- 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
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

et

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

#Using the simplePaginate Method

La méthode simplePaginate est très similaire à la méthode paginate mais avec une différence clé. La méthode simplePaginate ne récupère pas le nombre total d'enregistrements dans l'ensemble de données.

Comme nous venons de le voir, lorsque nous utilisons la méthode paginate, nous obtenons également des informations sur le nombre total d'enregistrements et de pages disponibles dans l'ensemble de données. Nous pouvons ensuite utiliser ces informations pour afficher des choses comme le nombre total de pages dans l'interface utilisateur ou la réponse API.

Mais si vous n'avez pas l'intention d'afficher ces détails à l'utilisateur (ou développeur consommant l'API), nous pouvons éviter une requête de base de données inutile (qui compte le nombre total d'enregistrements) en utilisant la méthode simplePaginate.

La méthode simplePaginate peut être utilisée de la même manière que la méthode 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

exécuter le code ci-dessus entraînerait la $users être une instance de IlluminateContractsPaginationPaginator, généralement un objet IlluminatePaginationPaginator.

Contrairement à l'objet

renvoyé par la méthode IlluminatePaginationLengthAwarePaginator, l'objet paginate ne contient pas d'informations sur le nombre total d'enregistrements dans l'ensemble de données et n'a aucune idée du nombre de pages ou d'enregistrements totaux. Il connaît simplement la page actuelle des données et s'il y a plus d'enregistrements à récupérer. IlluminatePaginationPaginator

#Using

avec vues de lame simplePaginate

Voyons comment vous pouvez utiliser la méthode

avec une vue de lame. Nous supposerons que nous avons le même itinéraire qu'auparavant, mais cette fois, nous utilisons la méthode 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>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Nous construirons notre vue de la lame de la même manière qu'auparavant:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('paginate', function () {
    return User::query()->paginate();
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
La page résultante ressemblerait à ceci:

Comme nous pouvons le voir dans cet exemple, la sortie de

est différente de la sortie que nous avons vue lors de l'utilisation de la méthode $users->links(). Étant donné que la méthode paginate ne récupère pas le nombre total d'enregistrements, il n'a aucun contexte du nombre total de pages ou d'enregistrements, seulement s'il y a une page suivante ou non. Par conséquent, nous ne voyons que les liens "précédents" et "suivants" dans les liens de pagination. simplePaginate

#Using

dans les points de terminaison de l'API simplePaginate

Vous pouvez également utiliser la méthode

dans les points de terminaison de l'API. Laravel convertira automatiquement les données paginées en JSON pour vous. simplePaginate

Créons un point de terminaison

qui renvoie les utilisateurs paginés au format JSON: /api/users

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Lorsque nous aurons atteint cette voie, nous obtiendrons une réponse JSON similaire à ce qui suit (j'ai limité le champ data à seulement 3 enregistrements pour Brevity):

<!-- 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme nous pouvons le voir, la réponse JSON est très similaire à la réponse que nous avons obtenue lors de l'utilisation de la méthode paginate. La principale différence est que nous n'avons pas les champs last_page, last_page_url, links ou total dans la réponse.

#Les requêtes SQL sous-jacentes

Jetons un coup d'œil aux requêtes SQL sous-jacentes qui sont exécutées lorsque vous utilisez la méthode simplePaginate.

La méthode simplePaginate repose toujours sur les valeurs limit et offset pour récupérer le sous-ensemble de données de la base de données. Cependant, il n'exécute pas la requête pour récupérer le nombre total d'enregistrements dans l'ensemble de données.

La valeur offset est toujours calculée de la même manière qu'auparavant:

<!-- 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>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cependant, la valeur limit est calculée légèrement différemment de la méthode paginate. Il est calculé comme:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('paginate', function () {
    return User::query()->paginate();
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

En effet, la méthode simplePaginate doit récupérer un enregistrement de plus que la valeur perPage pour déterminer s'il y a plus d'enregistrements à récupérer. Par exemple, disons que nous récupérons 15 enregistrements par page. La valeur limit serait 16. Donc, si 16 enregistrements devaient être retournés, nous saurions qu'il y a au moins une page de données supplémentaire disponible pour récupérer. Si moins de 16 enregistrements ont été retournés, nous saurions que nous sommes sur la dernière page de données.

Donc, si nous voulions récupérer la première page d'utilisateurs (avec 15 utilisateurs par page), les requêtes SQL suivantes seraient exécutées:

<!-- 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
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La requête de la deuxième page aurait l'air:

<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
Copier après la connexion
Copier après la connexion
Copier après la connexion

#Using the cursorPaginate Method

Jusqu'à présent, nous avons examiné les méthodes paginate et simplePaginate qui utilisent la pagination basée sur le décalage. Nous allons maintenant jeter un œil à la méthode cursorPaginate qui utilise la pagination basée sur le curseur.

En tant que tête-à-tête, la pagination basée sur le curseur peut sembler un peu déroutante la première fois que vous le rencontrez. Alors ne vous inquiétez pas si vous ne l'obtenez pas tout de suite. Espérons que, à la fin de cet article, vous comprenez mieux comment cela fonctionne. Je vais également laisser une vidéo impressionnante à la fin de cet article qui explique plus en détail la pagination basée sur le curseur.

Avec une pagination basée sur le décalage, nous utilisons les valeurs limit et offset pour récupérer un sous-ensemble de données de la base de données. Nous pouvons donc dire "sauter les 10 premiers enregistrements et récupérer les 10 enregistrements suivants". C'est simple à comprendre et facile à mettre en œuvre. Alors qu'avec la pagination du curseur, nous utilisons un curseur (généralement un identifiant unique pour un enregistrement spécifique dans la base de données) comme point de départ pour récupérer l'ensemble précédent / suivant d'enregistrements.

Par exemple, disons que nous faisons une requête pour récupérer les 15 premiers utilisateurs. Nous supposerons que l'ID du 15e utilisateur est de 20. Lorsque nous voulons récupérer les 15 utilisateurs suivants, nous utiliserons l'ID du 15e utilisateur (20) comme curseur. Nous dirons "Reprendre les 15 utilisateurs suivants avec un ID supérieur à 20".

Vous pouvez parfois voir des curseurs appelés "jetons", "clés", "suivants", "précédents", et ainsi de suite. Ils sont essentiellement une référence à un enregistrement spécifique dans la base de données. Nous examinerons la structure des curseurs plus tard dans cette section lorsque nous examinerons les requêtes SQL sous-jacentes.

Laravel nous permet d'utiliser facilement la pagination basée sur le curseur avec la méthode cursorPaginate:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Exécuter le code ci-dessus entraînerait le champ $users étant une instance de IlluminateContractsPaginationCursorPaginator, généralement un objet IlluminatePaginationCursorPaginator. Cette instance de paginateur contient toutes les informations dont vous avez besoin pour afficher les données paginées dans votre application.

Semblable à la méthode simplePaginate, la méthode cursorPaginate ne récupère pas le nombre total d'enregistrements dans l'ensemble de données. Il ne connaît que la page actuelle des données et s'il y a plus d'enregistrements à récupérer, nous ne sommes donc pas immédiatement conscients du nombre total de pages ou d'enregistrements.

#Using cursorPaginate avec vues de lame

Voyons comment utiliser la méthode cursorPaginate lors de la création de données dans une vue de lame. Semblable à nos exemples précédents, nous supposerons que nous avons un itinéraire simple qui récupère les utilisateurs de la base de données dans un format paginé et les transmets à une vue:

<!-- 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La vue de la lame peut ressembler à ceci:

<!-- 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>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela publierait une page similaire à ce qui suit:

Comme nous pouvons le voir, car la méthode cursorPaginate ne récupère pas le nombre total d'enregistrements dans l'ensemble de données, la sortie de $users->links() est similaire à la sortie que nous avons vue lors de l'utilisation de la méthode simplePaginate. Nous ne voyons que les liens "précédents" et "suivants" dans les liens de pagination.

#Using cursorPaginate dans les points de terminaison de l'API

Laravel vous permet également d'utiliser la méthode cursorPaginate dans les points de terminaison de l'API et convertira automatiquement les données paginées en JSON pour nous.

Créons un point de terminaison /api/users qui renvoie les utilisateurs paginés au format JSON:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('paginate', function () {
    return User::query()->paginate();
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Lorsque nous aurons atteint cette voie, nous obtiendrons une réponse JSON similaire à ce qui suit (j'ai limité le champ data à seulement 3 enregistrements pour Brevity):

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme nous pouvons le voir, la réponse JSON est similaire aux réponses précédentes que nous avons vues mais avec quelques petites différences. Comme nous ne récupérons pas le nombre total d'enregistrements, nous n'avons pas les champs last_page, last_page_url, links ou total dans la réponse. Vous avez peut-être aussi remarqué que nous n'avons pas non plus les champs from et to.

Au lieu de cela, nous avons les champs next_cursor et prev_cursor qui contiennent le curseur pour les pages de données suivantes et précédentes. Puisque nous sommes sur la première page, les champs prev_cursor sont tous les deux prev_page_url. Cependant, les champs null et next_cursor sont définis. next_page_url

Le champ

est une chaîne codée de base-64 qui contient le curseur pour la page suivante des données. Si nous décodons le champ next_cursor, nous obtiendrions quelque chose comme ça (embelli pour la lisibilité): next_cursor

<!-- 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Le curseur contient deux informations distinctes:

  • - L'ID du dernier enregistrement obtenu dans l'ensemble de données. users.id
  • - Une valeur booléenne qui nous indique si le curseur pointe vers l'ensemble d'éléments suivant ou précédent. Si la valeur est _pointsToNextItems, cela signifie que le curseur doit être utilisé pour récupérer l'ensemble suivant d'enregistrements avec un ID supérieur à la valeur true. Si la valeur est users.id, cela signifie que le curseur doit être utilisé pour récupérer l'ensemble des enregistrements précédents avec un ID inférieur à la valeur false. users.id
Voyons à quoi pourrait ressembler la deuxième page de données (encore une fois, raccourci à 3 enregistrements pour la concision):

<!-- 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>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Nous pouvons voir que les champs

et prev_cursor sont maintenant définis, et les champs prev_page_url et next_cursor ont été mis à jour avec le curseur pour la page suivante des données. next_page_url

#Les requêtes SQL sous-jacentes

Pour mieux comprendre comment la pagination du curseur fonctionne sous le capot, jetons un coup d'œil aux requêtes SQL sous-jacentes qui sont exécutées lorsque vous utilisez la méthode

. cursorPaginate

Sur la première page des données (contenant 15 enregistrements), la requête SQL suivante serait exécutée:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('paginate', function () {
    return User::query()->paginate();
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Nous pouvons voir que nous récupérons les 16 premiers enregistrements du tableau

et les commandons par la colonne users dans l'ordre croissant. Semblable à la méthode id, nous récupérons 16 lignes parce que nous voulons déterminer s'il y a plus d'enregistrements à récupérer. simplePaginate

Imaginons que nous naviguons ensuite vers la page suivante des éléments avec le curseur suivant:

<!-- 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
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Lorsque ce curseur est décodé, nous obtenons l'objet JSON suivant:

<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
Copier après la connexion
Copier après la connexion
Copier après la connexion
Laravel exécutera ensuite la requête SQL suivante pour récupérer le prochain ensemble d'enregistrements:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme nous pouvons le voir, nous récupérons les 16 enregistrements suivants du tableau users qui ont un id supérieur à 15 (depuis 15 était le dernier identifiant de la page précédente).

Supposons maintenant que l'ID du premier utilisateur à la page 2 est 16. Lorsque nous retournons à la première page des données de la deuxième page, le curseur suivant serait utilisé:

<!-- 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Lorsque cela est décodé, nous obtenons l'objet JSON suivant:

<!-- 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>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Lorsque nous passons à la page suivante des résultats, le dernier enregistrement récupéré est utilisé comme curseur. Lorsque nous retournons à la page précédente des résultats, le premier enregistrement récupéré est utilisé comme curseur. Pour cette raison, nous pouvons voir que la valeur users.id est définie sur 16 dans le curseur. Nous pouvons également voir que la valeur _pointsToNextItems est définie sur false parce que nous revenons à l'ensemble des éléments précédents.

En conséquence, la requête SQL suivante serait exécutée pour récupérer l'ensemble des enregistrements précédents:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('paginate', function () {
    return User::query()->paginate();
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme nous pouvons le voir, la contrainte where vérifie maintenant les enregistrements avec un id moins de 16 (puisque 16 a été le premier ID à la page 2) et les résultats sont commandés par ordre décroissant.

#Using API Ressources avec pagination

Jusqu'à présent, dans nos exemples d'API, nous venons de renvoyer les données paginées directement du contrôleur. Cependant, dans une application du monde réel, vous voudrez probablement traiter les données avant de les renvoyer à l'utilisateur. Cela pourrait être quelque chose de l'ajout ou de la suppression des champs, de la conversion des types de données ou même de la transformation des données en un format différent. Pour cette raison, vous voudrez probablement utiliser les ressources API car ils vous fournissent un moyen de transformer systématiquement vos données avant de les renvoyer.

Laravel vous permet d'utiliser des ressources API aux côtés de la pagination. Regardons un exemple de la façon de procéder.

Imaginez que nous avons créé une classe de ressources API AppHttpResourcesUserResource qui transforme les données de l'utilisateur avant de les renvoyer. Cela pourrait ressembler à ceci:

<!-- 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
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans la méthode toArray, nous définissons que chaque fois que nous traitons un utilisateur via cette ressource, nous voulons seulement retourner les champs id, name et email.

Maintenant, créons un point de terminaison simple /api/users API dans notre fichier routes/api.php qui renvoie les utilisateurs paginés à l'aide du AppHttpResourcesUserResource:

<!-- Syntax highlighted by torchlight.dev -->select count(*) as aggregate from `users`
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans le code ci-dessus, nous récupérons une seule page d'utilisateurs (supposons que c'est la première page contenant 15 utilisateurs) de la base de données. Nous passons ensuite le champ $users (qui sera une instance de IlluminatePaginationLengthAwarePaginator) à la méthode UserResource::collection. Cette méthode transformera les données paginées à l'aide du AppHttpResourcesUserResource avant de les renvoyer à l'utilisateur.

Lorsque nous atteindrons le point final /api/users, nous obtiendrons une réponse JSON similaire à ce qui suit (j'ai limité le champ data à seulement 3 enregistrements pour la concitation):

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Comme nous pouvons le voir dans le JSON ci-dessus, Laravel détecte que nous travaillons avec un ensemble de données paginé et renvoie les données paginées dans un format similaire qu'auparavant. Cependant, cette fois, les utilisateurs du champ data ne contiennent que les champs id, name et email que nous avons spécifiés dans notre classe de ressources API. D'autres champs (current_page, from, last_page, links, path, per_page, to, et total) sont toujours retournés car ils font partie des données paginées, mais elles ont été placées à l'intérieur d'un champ meta. Il y a aussi un champ links qui contient les liens first, last, prev et next vers les différentes pages de données.

#changage de la valeur par page

Lors de la création de vues avec des données paginées, vous souhaiterez peut-être permettre à l'utilisateur de modifier le nombre d'enregistrements affichés par page. Cela peut être via une liste déroulante ou un champ de saisie du nombre.

Laravel facilite la modification du nombre d'enregistrements affichés par page en passant un paramètre perPage aux méthodes simplePaginate, paginate et cursorPaginate. Ce paramètre vous permet de spécifier le nombre d'enregistrements que vous souhaitez afficher par page.

Jetons un coup d'œil à un exemple simple de la façon de lire un paramètre de requête per_page et d'utiliser ceci pour modifier le nombre d'enregistrements récupérés par page:

<!-- 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,
    ]);
});
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans l'exemple ci-dessus, nous saisissons la valeur du paramètre de requête per_page. Si la valeur n'est pas fournie, nous allons par défaut 10. Nous passons ensuite cette valeur au paramètre perPage de la méthode paginate.

Nous pourrions ensuite accéder à ces différentes URL:

  • https://my-app.com/users - Affichez la première page d'utilisateurs avec 10 enregistrements par page.
  • https://my-app.com/users?per_page=5 - Affichez la première page des utilisateurs avec 5 enregistrements par page.
  • https://my-app.com/users?per_page=5&page=2 - Affichez la deuxième page des utilisateurs avec 5 enregistrements par page.
  • et ainsi de suite ...

#Comment pour décider quelle méthode de pagination utiliser

Maintenant que nous avons examiné les différents types de pagination et comment les utiliser dans Laravel, nous discuterons de la façon de décider laquelle de ces approches utiliser dans votre application.

# Vous avez besoin du numéro de page ou du nombre total d'enregistrements?

Si vous construisez un point de terminaison d'interface utilisateur ou d'API qui nécessite que le nombre total d'enregistrements ou de pages soit affiché, alors la méthode paginate est probablement un choix judicieux.

Si vous n'avez pas besoin de ces éléments, alors les simplePaginate ou cursorPaginate seront plus efficaces car ils n'effectuent pas des requêtes inutiles pour compter le nombre total d'enregistrements.

# Vous devez passer à une page spécifique?

Si vous avez besoin de pouvoir passer à une page spécifique de données, la pagination basée sur le décalage est plus appropriée. Étant donné que la pagination du curseur est avec état, elle s'appuie sur la page précédente pour savoir où aller ensuite. Il n'est donc pas aussi facile de passer à une page spécifique.

Alors que lorsque vous utilisez une pagination de décalage, vous pouvez généralement passer le numéro de page dans la demande (peut-être comme paramètre de requête) et sauter sur cette page sans avoir aucun contexte de la page précédente.

#Wow Large est l'ensemble de données?

En raison de la façon dont les bases de données gèrent les valeurs offset, la pagination basée sur le décalage devient moins efficace à mesure que le numéro de page augmente. En effet, lorsque vous utilisez un décalage, la base de données doit toujours parcourir tous les enregistrements jusqu'à la valeur de décalage. Ils sont juste jetés et ne sont pas retournés dans les résultats de la requête.

Voici un excellent article qui explique cela plus en détail: https://use-the-index-luke.com/no-offset.

Ainsi, à mesure que la quantité totale de données dans la base de données augmente et que le nombre de pages augmente, la pagination basée sur le décalage peut devenir moins efficace. Dans ces cas, la pagination basée sur le curseur est plus performante, surtout si le champ de curseur est indexé, car les enregistrements précédents ne sont pas lus. Pour cette raison, si vous allez utiliser une pagination contre un grand ensemble de données, vous voudrez peut-être opter pour la pagination du curseur sur la pagination de décalage.

# L'ensemble de données est-il susceptible de changer souvent?

La pagination basée sur le décalage peut souffrir de problèmes si l'ensemble de données sous-jacent change entre les demandes.

Jetons un coup d'œil à un exemple.

Disons que nous avons les 10 utilisateurs suivants dans notre base de données:

  • utilisateur 1
  • utilisateur 2
  • utilisateur 3
  • utilisateur 4
  • utilisateur 5
  • utilisateur 6
  • utilisateur 7
  • utilisateur 8
  • utilisateur 9
  • utilisateur 10

Nous faisons une demande pour récupérer la première page (contenant 5 utilisateurs) et obtenir les utilisateurs suivants:

  • utilisateur 1
  • utilisateur 2
  • utilisateur 3
  • utilisateur 4
  • utilisateur 5

Lorsque nous naviguons vers la page 2, nous nous attendons à obtenir des utilisateurs de 6 à 10. Cependant, imaginons qu'avant de charger la page 2 (pendant que nous consulons toujours la page 1), l'utilisateur 1 est supprimé de la base de données. Étant donné que la taille de la page est de 5, la requête pour récupérer la page suivante ressemblerait à ceci:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela signifie que nous sautons les 5 premiers enregistrements et récupérons les 5.

suivants

Cela entraînerait la page 2 contenant les utilisateurs suivants:

  • utilisateur 7
  • utilisateur 8
  • utilisateur 9
  • utilisateur 10

Comme nous pouvons le voir, l'utilisateur 6 manque dans la liste. En effet

La pagination basée sur le curseur n'a pas ce problème, car nous ne sautons pas les enregistrements, nous allons simplement récupérer le prochain ensemble d'enregistrements basé sur un curseur. Imaginons que nous avions utilisé une pagination basée sur le curseur dans l'exemple ci-dessus. Le curseur de la page 2 serait l'ID de l'utilisateur 5 (que nous supposerons est 5) car il s'agissait du dernier enregistrement de la première page. Ainsi, notre requête pour la page 2 peut ressembler à ceci:

<!-- Syntax highlighted by torchlight.dev -->use App\Models\User;

$users = User::query()->paginate();
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

exécuter la requête ci-dessus renverrait les utilisateurs 6 à 10 comme prévu.

Cela devrait, espérons-le, mettre en évidence la façon dont la pagination basée sur le décalage peut devenir problématique lorsque les données sous-jacentes sont modifiées, ajoutées ou supprimées pendant la lecture. Il devient moins prévisible et peut conduire à des résultats inattendus.

# êtes-vous en train de construire une API?

Il est important de se rappeler que vous n'êtes pas fixé à l'utilisation d'un seul type de pagination dans votre application. Dans certains endroits, la pagination de compensation pourrait être plus appropriée (peut-être à des fins d'interface utilisateur) et dans d'autres, la pagination du curseur pourrait être plus efficace (comme lorsque vous travaillez avec un grand ensemble de données). Vous pouvez donc mélanger et assortir des méthodes de pagination dans votre application en fonction du cas d'utilisation.

Cependant, si vous construisez une API, je vous recommande vivement que vous soyez cohérent et utilisez une seule approche de pagination pour tous vos points de terminaison. Cela permettra aux développeurs de comprendre comment utiliser votre API et d'éviter toute confusion.

Vous ne voulez pas qu'ils aient à se rappeler quels points de terminaison utilisent la pagination décalée et lesquelles utilisent la curseur-pagination.

Bien sûr, ce n'est pas une règle stricte et rapide. Si vous avez vraiment besoin d'utiliser une méthode de pagination différente dans un point de terminaison particulier, allez-y. Mais assurez-vous simplement de le comprendre dans la documentation pour faciliter la compréhension des développeurs.

#prefer une vidéo à la place?

Si vous êtes plus un apprenant visuel, vous voudrez peut-être consulter cette vidéo impressionnante d'Aaron Francis qui explique la différence entre la pagination offset et basée sur le curseur plus en détail:

#conclusion

Dans cet article, nous avons examiné les différents types de pagination à Laravel et comment les utiliser. Nous avons également examiné leurs requêtes SQL sous-jacentes et comment décider quelle méthode de pagination utiliser dans votre application.

J'espère que vous devriez maintenant vous sentir plus confiant dans l'utilisation de la pagination dans vos applications Laravel.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal