Estamos actualizando el sitio. Durante unos días es posible que veas fallos de diseño o de traducción. La documentación sigue disponible: si una página se ve mal, recárgala más tarde.

Inicio Laravel 10.x Base de datos: Paginación

Base de datos: Paginación

10.x 7 de mar. de 2026

#Introducción

En otros frameworks, la paginación puede ser muy complicada. Esperamos que el enfoque de Laravel para la paginación sea un soplo de aire fresco. El paginador de Laravel está integrado con el query builder y el Eloquent ORM y ofrece una paginación conveniente y fácil de usar para registros de base de datos sin necesidad de configuración.

Por defecto, el HTML generado por el paginador es compatible con el framework Tailwind CSS; sin embargo, también está disponible el soporte para paginación con Bootstrap.

#Tailwind JIT

Si está utilizando las vistas de paginación predeterminadas de Tailwind de Laravel y el motor Tailwind JIT, debe asegurarse de que la clave content en el archivo tailwind.config.js de su aplicación haga referencia a las vistas de paginación de Laravel para que sus clases Tailwind no sean eliminadas:

content: [
    './resources/**/*.blade.php',
    './resources/**/*.js',
    './resources/**/*.vue',
    './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
],

#Uso básico

#Paginando resultados del Query Builder

Hay varias formas de paginar elementos. La más sencilla es usar el método paginate en el query builder o en una consulta de Eloquent. El método paginate se encarga automáticamente de establecer el "limit" y "offset" de la consulta según la página actual que el usuario está viendo. Por defecto, la página actual se detecta por el valor del argumento page en la cadena de consulta HTTP. Este valor es detectado automáticamente por Laravel y también se inserta automáticamente en los enlaces generados por el paginador.

En este ejemplo, el único argumento pasado al método paginate es el número de elementos que desea mostrar "por página". En este caso, especifiquemos que queremos mostrar 15 elementos por página:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * Mostrar todos los usuarios de la aplicación.
     */
    public function index(): View
    {
        return view('user.index', [
            'users' => DB::table('users')->paginate(15)
        ]);
    }
}

#Paginación simple

El método paginate cuenta el número total de registros que coinciden con la consulta antes de recuperar los registros de la base de datos. Esto se hace para que el paginador sepa cuántas páginas de registros hay en total. Sin embargo, si no planea mostrar el número total de páginas en la interfaz de usuario de su aplicación, la consulta para contar registros es innecesaria.

Por lo tanto, si solo necesita mostrar enlaces simples de "Siguiente" y "Anterior" en la interfaz de usuario de su aplicación, puede usar el método simplePaginate para realizar una consulta única y eficiente:

$users = DB::table('users')->simplePaginate(15);

#Paginando resultados de Eloquent

También puede paginar consultas de Eloquent. En este ejemplo, paginaremos el modelo App\Models\User e indicaremos que planeamos mostrar 15 registros por página. Como puede ver, la sintaxis es casi idéntica a la paginación de resultados del query builder:

use App\Models\User;

$users = User::paginate(15);

Por supuesto, puede llamar al método paginate después de establecer otras restricciones en la consulta, como cláusulas where:

$users = User::where('votes', '>', 100)->paginate(15);

También puede usar el método simplePaginate al paginar modelos Eloquent:

$users = User::where('votes', '>', 100)->simplePaginate(15);

De manera similar, puede usar el método cursorPaginate para paginar modelos Eloquent con cursor:

$users = User::where('votes', '>', 100)->cursorPaginate(15);

#Múltiples instancias de paginador por página

A veces puede necesitar renderizar dos paginadores separados en una sola pantalla que su aplicación muestra. Sin embargo, si ambas instancias de paginador usan el parámetro de cadena de consulta page para almacenar la página actual, los dos paginadores entrarán en conflicto. Para resolver este conflicto, puede pasar el nombre del parámetro de cadena de consulta que desea usar para almacenar la página actual del paginador mediante el tercer argumento de los métodos paginate, simplePaginate y cursorPaginate:

use App\Models\User;

$users = User::where('votes', '>', 100)->paginate(
    $perPage = 15, $columns = ['*'], $pageName = 'users'
);

#Paginación con cursor

Mientras que paginate y simplePaginate crean consultas usando la cláusula SQL "offset", la paginación con cursor funciona construyendo cláusulas "where" que comparan los valores de las columnas ordenadas contenidas en la consulta, proporcionando el rendimiento de base de datos más eficiente entre todos los métodos de paginación de Laravel. Este método de paginación es especialmente adecuado para conjuntos de datos grandes y para interfaces de usuario con desplazamiento "infinito".

A diferencia de la paginación basada en offset, que incluye un número de página en la cadena de consulta de las URLs generadas por el paginador, la paginación basada en cursor coloca una cadena "cursor" en la cadena de consulta. El cursor es una cadena codificada que contiene la ubicación desde donde la siguiente consulta paginada debe comenzar y la dirección en la que debe paginar:

http://localhost/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0

Puede crear una instancia de paginador basada en cursor mediante el método cursorPaginate que ofrece el query builder. Este método devuelve una instancia de Illuminate\Pagination\CursorPaginator:

$users = DB::table('users')->orderBy('id')->cursorPaginate(15);

Una vez que haya obtenido una instancia de cursor paginator, puede mostrar los resultados de paginación como normalmente lo haría al usar los métodos paginate y simplePaginate. Para más información sobre los métodos de instancia que ofrece el cursor paginator, consulte la documentación de métodos de instancia del cursor paginator.

Внимание

Su consulta debe contener una cláusula "order by" para poder aprovechar la paginación con cursor. Además, las columnas por las que se ordena la consulta deben pertenecer a la tabla que está paginando.

#Paginación con cursor vs. paginación con offset

Para ilustrar las diferencias entre la paginación con offset y la paginación con cursor, examinemos algunas consultas SQL de ejemplo. Ambas consultas mostrarán la "segunda página" de resultados para una tabla users ordenada por id:

# Paginación con offset...
select * from users order by id asc limit 15 offset 15;

# Paginación con cursor...
select * from users where id > 15 order by id asc limit 15;

La consulta de paginación con cursor ofrece las siguientes ventajas sobre la paginación con offset:

  • Para conjuntos de datos grandes, la paginación con cursor ofrecerá mejor rendimiento si las columnas "order by" están indexadas. Esto se debe a que la cláusula "offset" escanea todos los datos previamente coincidentes.
  • Para conjuntos de datos con escrituras frecuentes, la paginación con offset puede omitir registros o mostrar duplicados si se han agregado o eliminado resultados recientemente en la página que el usuario está viendo.

Sin embargo, la paginación con cursor tiene las siguientes limitaciones:

  • Al igual que simplePaginate, la paginación con cursor solo puede usarse para mostrar enlaces de "Siguiente" y "Anterior" y no soporta generar enlaces con números de página.
  • Requiere que el ordenamiento se base en al menos una columna única o una combinación de columnas que sean únicas. No se soportan columnas con valores null.
  • Las expresiones de consulta en cláusulas "order by" solo se soportan si están aliasadas y también añadidas a la cláusula "select".
  • No se soportan expresiones de consulta con parámetros.

#Creando un paginador manualmente

A veces puede desear crear una instancia de paginación manualmente, pasando un arreglo de elementos que ya tiene en memoria. Puede hacerlo creando una instancia de Illuminate\Pagination\Paginator, Illuminate\Pagination\LengthAwarePaginator o Illuminate\Pagination\CursorPaginator, según sus necesidades.

Las clases Paginator y CursorPaginator no necesitan conocer el número total de elementos en el conjunto de resultados; sin embargo, por esta razón, estas clases no tienen métodos para obtener el índice de la última página. El LengthAwarePaginator acepta casi los mismos argumentos que el Paginator; sin embargo, requiere un conteo del número total de elementos en el conjunto de resultados.

En otras palabras, el Paginator corresponde al método simplePaginate del query builder, el CursorPaginator corresponde al método cursorPaginate, y el LengthAwarePaginator corresponde al método paginate.

Внимание

Al crear manualmente una instancia de paginador, debe "cortar" manualmente el arreglo de resultados que pasa al paginador. Si no está seguro de cómo hacerlo, consulte la función PHP array_slice.

#Personalizando URLs de paginación

Por defecto, los enlaces generados por el paginador coincidirán con el URI de la solicitud actual. Sin embargo, el método withPath del paginador le permite personalizar el URI usado por el paginador al generar enlaces. Por ejemplo, si desea que el paginador genere enlaces como http://example.com/admin/users?page=N, debe pasar /admin/users al método withPath:

use App\Models\User;

Route::get('/users', function () {
    $users = User::paginate(15);

    $users->withPath('/admin/users');

    // ...
});

#Agregando valores a la cadena de consulta

Puede agregar valores a la cadena de consulta de los enlaces de paginación usando el método appends. Por ejemplo, para agregar sort=votes a cada enlace de paginación, debe hacer la siguiente llamada a appends:

use App\Models\User;

Route::get('/users', function () {
    $users = User::paginate(15);

    $users->appends(['sort' => 'votes']);

    // ...
});

Puede usar el método withQueryString si desea agregar todos los valores actuales de la cadena de consulta de la solicitud a los enlaces de paginación:

$users = User::paginate(15)->withQueryString();

#Agregando fragmentos hash

Si necesita agregar un "fragmento hash" a las URLs generadas por el paginador, puede usar el método fragment. Por ejemplo, para agregar #users al final de cada enlace de paginación, debe invocar el método fragment así:

$users = User::paginate(15)->fragment('users');

#Mostrando resultados de paginación

Al llamar al método paginate, recibirá una instancia de Illuminate\Pagination\LengthAwarePaginator, mientras que llamar al método simplePaginate devuelve una instancia de Illuminate\Pagination\Paginator. Finalmente, llamar al método cursorPaginate devuelve una instancia de Illuminate\Pagination\CursorPaginator.

Estos objetos proporcionan varios métodos que describen el conjunto de resultados. Además de estos métodos auxiliares, las instancias del paginador son iteradores y pueden recorrerse como un arreglo. Por lo tanto, una vez que haya obtenido los resultados, puede mostrar los resultados y renderizar los enlaces de página usando Blade:

<div class="container">
    @foreach ($users as $user)
        {{ $user->name }}
    @endforeach
</div>

{{ $users->links() }}

El método links renderizará los enlaces al resto de las páginas en el conjunto de resultados. Cada uno de estos enlaces ya contendrá la variable de cadena de consulta page adecuada. Recuerde que el HTML generado por el método links es compatible con el framework Tailwind CSS.

Cuando el paginador muestra enlaces de paginación, se muestra el número de la página actual así como enlaces para las tres páginas antes y después de la página actual. Usando el método onEachSide, puede controlar cuántos enlaces adicionales se muestran a cada lado de la página actual dentro de la ventana deslizante de enlaces generada por el paginador:

{{ $users->onEachSide(5)->links() }}

#Convirtiendo resultados a JSON

Las clases de paginador de Laravel implementan el contrato de interfaz Illuminate\Contracts\Support\Jsonable y exponen el método toJson, por lo que es muy fácil convertir sus resultados de paginación a JSON. También puede convertir una instancia de paginador a JSON retornándola desde una ruta o acción de controlador:

use App\Models\User;

Route::get('/users', function () {
    return User::paginate();
});

El JSON del paginador incluirá información meta como total, current_page, last_page y más. Los registros de resultados están disponibles a través de la clave data en el arreglo JSON. Aquí hay un ejemplo del JSON creado al retornar una instancia de paginador desde una ruta:

{
   "total": 50,
   "per_page": 15,
   "current_page": 1,
   "last_page": 4,
   "first_page_url": "http://laravel.app?page=1",
   "last_page_url": "http://laravel.app?page=4",
   "next_page_url": "http://laravel.app?page=2",
   "prev_page_url": null,
   "path": "http://laravel.app",
   "from": 1,
   "to": 15,
   "data":[
        {
            // Record...
        },
        {
            // Record...
        }
   ]
}

#Personalizando la vista de paginación

Por defecto, las vistas renderizadas para mostrar los enlaces de paginación son compatibles con el framework Tailwind CSS. Sin embargo, si no está usando Tailwind, puede definir sus propias vistas para renderizar estos enlaces. Al llamar al método links en una instancia de paginador, puede pasar el nombre de la vista como primer argumento del método:

{{ $paginator->links('view.name') }}

<!-- Pasando datos adicionales a la vista... -->
{{ $paginator->links('view.name', ['foo' => 'bar']) }}

Sin embargo, la forma más sencilla de personalizar las vistas de paginación es exportándolas a su directorio resources/views/vendor usando el comando vendor:publish:

php artisan vendor:publish --tag=laravel-pagination

Este comando colocará las vistas en el directorio resources/views/vendor/pagination de su aplicación. El archivo tailwind.blade.php dentro de este directorio corresponde a la vista de paginación predeterminada. Puede editar este archivo para modificar el HTML de la paginación.

Si desea designar un archivo diferente como la vista de paginación predeterminada, puede invocar los métodos defaultView y defaultSimpleView del paginador dentro del método boot de su clase App\Providers\AppServiceProvider:

<?php

namespace App\Providers;

use Illuminate\Pagination\Paginator;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Inicializar cualquier servicio de la aplicación.
     */
    public function boot(): void
    {
        Paginator::defaultView('view-name');

        Paginator::defaultSimpleView('view-name');
    }
}

#Usando Bootstrap

Laravel incluye vistas de paginación construidas con Bootstrap CSS. Para usar estas vistas en lugar de las vistas predeterminadas de Tailwind, puede llamar a los métodos useBootstrapFour o useBootstrapFive del paginador dentro del método boot de su clase App\Providers\AppServiceProvider:

use Illuminate\Pagination\Paginator;

/**
 * Inicializar cualquier servicio de la aplicación.
 */
public function boot(): void
{
    Paginator::useBootstrapFive();
    Paginator::useBootstrapFour();
}

#Métodos de instancia de Paginator / LengthAwarePaginator

Cada instancia de paginador proporciona información adicional de paginación mediante los siguientes métodos:

Método Descripción
$paginator->count() Obtener el número de elementos para la página actual.
$paginator->currentPage() Obtener el número de la página actual.
$paginator->firstItem() Obtener el número del primer elemento en los resultados.
$paginator->getOptions() Obtener las opciones del paginador.
$paginator->getUrlRange($start, $end) Crear un rango de URLs de paginación.
$paginator->hasPages() Determinar si hay suficientes elementos para dividir en múltiples páginas.
$paginator->hasMorePages() Determinar si hay más elementos en el almacén de datos.
$paginator->items() Obtener los elementos para la página actual.
$paginator->lastItem() Obtener el número del último elemento en los resultados.
$paginator->lastPage() Obtener el número de la última página disponible. (No disponible cuando se usa simplePaginate).
$paginator->nextPageUrl() Obtener la URL para la página siguiente.
$paginator->onFirstPage() Determinar si el paginador está en la primera página.
$paginator->perPage() El número de elementos que se mostrarán por página.
$paginator->previousPageUrl() Obtener la URL para la página anterior.
$paginator->total() Determinar el número total de elementos coincidentes en el almacén de datos. (No disponible cuando se usa simplePaginate).
$paginator->url($page) Obtener la URL para un número de página dado.
$paginator->getPageName() Obtener la variable de cadena de consulta usada para almacenar la página.
$paginator->setPageName($name) Establecer la variable de cadena de consulta usada para almacenar la página.
$paginator->through($callback) Transformar cada elemento usando un callback.

#Métodos de instancia de Cursor Paginator

Cada instancia de cursor paginator proporciona información adicional de paginación mediante los siguientes métodos:

Método Descripción
$paginator->count() Obtener el número de elementos para la página actual.
$paginator->cursor() Obtener la instancia del cursor actual.
$paginator->getOptions() Obtener las opciones del paginador.
$paginator->hasPages() Determinar si hay suficientes elementos para dividir en múltiples páginas.
$paginator->hasMorePages() Determinar si hay más elementos en el almacén de datos.
$paginator->getCursorName() Obtener la variable de cadena de consulta usada para almacenar el cursor.
$paginator->items() Obtener los elementos para la página actual.
$paginator->nextCursor() Obtener la instancia del cursor para el siguiente conjunto de elementos.
$paginator->nextPageUrl() Obtener la URL para la página siguiente.
$paginator->onFirstPage() Determinar si el paginador está en la primera página.
$paginator->onLastPage() Determinar si el paginador está en la última página.
$paginator->perPage() El número de elementos que se mostrarán por página.
$paginator->previousCursor() Obtener la instancia del cursor para el conjunto anterior de elementos.
$paginator->previousPageUrl() Obtener la URL para la página anterior.
$paginator->setCursorName() Establecer la variable de cadena de consulta usada para almacenar el cursor.
$paginator->url($cursor) Obtener la URL para una instancia de cursor dada.