🎃 ¡Oferta de Halloween! Obtén 40% de descuento en nuestros cursos hasta el 31 de octubre 🎃

1d: 7h: 46m:45s'
jonatan uran
jonatan uran
Laravel
Comparte:

Model-binding + cache

Tengo el siguiente conflicto para utilizar CACHE, dado que mi Controlador usa el Model-binding provisto por Laravel 

Enlace para mostrar un empleado:
<a href="{{ route('employee.show', $employee) }}">
  Enlace a show
</a>


web.php:
Route::get('employee/{employee}', [EmployeeController::class, 'show'])->name('employee.show');

app/Http/Controller/EmployeeController.php
class EmployeeController extends Controller
{
...
public function show(Employee $employee): View
{
return view('employees.show',compact('employee'));
}

Mi pregunta es: Cómo puedo hacer para que el llamado a mi función que usa el model-binding (que hace una consulta a la Base de Datos [select * from `employees` where `id` = 1 limit 1]) pueda utilizar cache y no ejecute esa consulta.

Actualmente lo solucioné enviando el id en lugar del objeto completo (quitando el model-binding):
Enlace para mostrar un empleado:
<a href="{{ route('employee.show', $employee->id) }}">
  Enlace a show
</a>

app/Http/Controller/EmployeeController.php
----------------------------------
class EmployeeController extends Controller
{
 ...

 public function show($id): View
 {
 $employee  = Cache::remember('employee.{$id}', 3600, function() use($id){
            return Employee::find($id);
        });

     return view('employees.show',compact('employee'));
 }

Pero quiero saber si existe alguna sintaxis que me permita seguir enviando el objeto completo y utilizar caché. 
Gracias
Luis Rodríguez
Luis Rodríguez (108 xp)
La sintaxis que estás buscando se llama "route model binding" en Laravel. Laravel te permite personalizar cómo se resuelven las dependencias en tus rutas. En este caso, deseas que, en lugar de pasar solo el id, puedas pasar el objeto Employee completo y aún así aprovechar el caché.

Para hacer esto, puedes personalizar el "binding" de modelos en tu archivo RouteServiceProvider. Aquí hay un ejemplo: 
// app/Providers/RouteServiceProvider.php

use App\Models\Employee;

class RouteServiceProvider extends ServiceProvider
{
    public function boot()
    {
        parent::boot();

        Route::bind('employee', function ($value) {
            // Si el valor es un número, asumimos que es un ID
            if (is_numeric($value)) {
                return Cache::remember("employee.{$value}", 3600, function () use ($value) {
                    return Employee::find($value);
                });
            }

            // Si es un objeto Employee, simplemente lo devolvemos
            if ($value instanceof Employee) {
                return $value;
            }

            // Puedes agregar lógica adicional aquí según tus necesidades

            return null;
        });
    }
}
Esta lógica personalizada en el bind verifica si el valor es un número, en cuyo caso asume que es un ID y lo busca en caché. Si ya es un objeto Employee, simplemente lo devuelve. Puedes personalizar esta lógica según tus necesidades específicas.
Ten en cuenta que esta personalización afectará todas las rutas que usen employee como parámetro de ruta en tu aplicación. 
2