En este post te voy a mostrar cómo puedes realizar una paginación en Laravel; es decir, mostrar registros (de la base de datos) por página, en lugar de mostrarlos todos a la vez.
Laravel ya provee una manera realmente sencilla de agregar paginación, incluso da la opción de agregar los enlaces a la página, y por supuesto, también permite cosas como la búsqueda u otros métodos del Query Builder, todo esto sin escribir ninguna consulta SQL manual.
Paginación simple
Si simplemente quieres paginar tus resultados, invoca a paginate
de tu modelo y pásale como argumento cuántos elementos quieres por página.
Por ejemplo, yo tengo mi modelo llamado Producto
:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Producto extends Model
{
protected $fillable = ["codigo_barras", "descripcion", "precio_compra", "precio_venta", "existencia", "es_servicio",
];
}
Ahora en mi controlador para enviarlo a la vista, indico el uso del namespace:
use App\Producto;
Y para paginar, envío los resultados así:
<?php
$productos = Producto::paginate(5);
return view("productos.productos_index", [
"productos" => $productos,
]);
En este caso estoy paginando cada 5 registros. Ahora en mi vista los dibujo en una tabla; puedo iterarlos fácilmente con un foreach
:
<table class="table table-bordered">
<thead>
<tr>
<th>Código de barras</th>
<th>Descripción</th>
<th>Precio de compra</th>
<th>Precio de venta</th>
<th>Utilidad</th>
<th>Existencia</th>
<th>¿Servicio?</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
</thead>
<tbody>
@foreach($productos as $producto)
<tr>
<td>{{$producto->codigo_barras}}</td>
<td>{{$producto->descripcion}}</td>
<td>{{$producto->precio_compra}}</td>
<td>{{$producto->precio_venta}}</td>
<td>{{$producto->precio_venta - $producto->precio_compra}}</td>
<td>{{$producto->existencia}}</td>
<td>
@if($producto->es_servicio)
<i class="fa fa-check"></i>
@else
<i class="fa fa-times"></i>
@endif
</td>
<td>
<a class="btn btn-warning" href="{{route("productos.edit",[$producto])}}">
<i class="fa fa-edit"></i>
</a>
</td>
<td>
<form action="{{route("productos.destroy", [$producto])}}" method="post">
@method("delete")
@csrf
<button type="submit" class="btn btn-danger">
<i class="fa fa-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
Además, si quiero que se muestren los enlaces para navegar a las distintas páginas (por defecto Laravel genera el HTML para Bootstrap) invoco a links
justo abajo de mi tabla:
{{$productos->links()}}
El código completo queda así:
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Código de barras</th>
<th>Descripción</th>
<th>Precio de compra</th>
<th>Precio de venta</th>
<th>Utilidad</th>
<th>Existencia</th>
<th>¿Servicio?</th>
<th>Editar</th>
<th>Eliminar</th>
</tr>
</thead>
<tbody>
@foreach($productos as $producto)
<tr>
<td>{{$producto->codigo_barras}}</td>
<td>{{$producto->descripcion}}</td>
<td>{{$producto->precio_compra}}</td>
<td>{{$producto->precio_venta}}</td>
<td>{{$producto->precio_venta - $producto->precio_compra}}</td>
<td>{{$producto->existencia}}</td>
<td>
@if($producto->es_servicio)
<i class="fa fa-check"></i>
@else
<i class="fa fa-times"></i>
@endif
</td>
<td>
<a class="btn btn-warning" href="{{route("productos.edit",[$producto])}}">
<i class="fa fa-edit"></i>
</a>
</td>
<td>
<form action="{{route("productos.destroy", [$producto])}}" method="post">
@method("delete")
@csrf
<button type="submit" class="btn btn-danger">
<i class="fa fa-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
{{$productos->links()}}
</div>
Si te fijas, toma el número de página de la URL. Por ejemplo, lo siguiente muestra la página 2:
http://localhost/nombre_de_tu_proyecto/public/productos?page=2
Fíjate en el parámetro de page
que está en 2
.
Paginación con búsqueda
Si quieres agregar filtros o aprovechar lo que ofrece el query builder, puedes invocar a varios métodos y al final paginar con paginate
.
Por ejemplo, supongamos que quieres filtrar los productos por búsqueda basándote en una variable de la URL, y que los quieres ordenar por descripción.
<?php
# Función llamada desde el controlador; es un ejemplo, tú puedes colocar el código donde gustes
public function index(Request $request)
{
$busqueda = "";
if ($request->get("busqueda")) {
$busqueda = $request->get("busqueda");
}
# Exista o no exista búsqueda, los ordenamos
$builder = Producto::orderBy("descripcion");
if ($busqueda) {
# Si hay búsqueda, agregamos el filtro
$builder->where("descripcion", "LIKE", "%$busqueda%");
}
# Al final de todo, invocamos a paginate que tendrá todos los filtros
$productos = $builder->paginate(5);
return view("productos.productos_index", [
"productos" => $productos,
]);
}
En este caso podemos invocar a todos los métodos para hacer consultas de SQL. Por ejemplo, estamos invocando a orderBy
y a where
; pero al final obtenemos los resultados con paginate
.
Todo sigue funcionando igual, haya búsqueda o no, y los links también funcionan. Si hay menos resultados para la búsqueda, el número de enlaces para páginas cambiará, es decir, se toman en cuenta todos los filtros y el total de registros devueltos.
Si no usas bootstrap
En caso de que no utilices el framework Bootstrap o quieras mostrar los enlaces de manera manual, también es posible. Puedes obtener el total de elementos accediendo a total
, así:
$productos->total();
Para saber cuántos mostrar por página (aunque eso también se define al invocar a paginate
, pero esto funciona para hacerlo desde la vista) invoca a perPage
.
Ya con esto puedes obtener las páginas así:
$paginas = ceil($productos->total() / $productos->perPage()
Y hacer un ciclo for que muestre los enlaces desde 1 hasta el total de páginas, justo como lo detallo en mi post de paginación manual de registros con PHP.
Recuerda que en este caso $productos
es lo que devuelve el método paginate
al invocarlo sobre un modelo.
Si te gusta este framework, te invito a ver más sobre Laravel en mi blog.
buen articulo
Excelente hermano, muchas gracias por tus conocimientos, que Dios le siga bendiciendo…