10 TRUCOS AVANZADOS DE LARAVEL ELOQUENT CON WITH
El problema N+1 es el dolor de cabeza clásico de todo desarrollador. Cargamos un modelo y, de repente, Laravel hace decenas (o cientos) de consultas extra para traer sus relaciones. La solución básica es with,with tiene un poder brutal que muy pocos aprovechan.En el post detectar problema N+1 en Laravel.
- Filtrar la relación al cargarla. En el ejemplo se cargan solo los comentarios aprobados y no se traen datos innecesarios.
Post::with(['comments' => fn($query) => $query->where('approved', true)]) ->get(); - Cargar relaciones anidadas en una sola línea: Se pueden anidar los campos todo lo que s quiera que Laravel lo resuelve en muy pocas consultas.
Post::with(['category', 'comments.user',...])->get(); - Seleccionar solo columnas específicas (ahorra memoria y ancho de banda).
Post::with('category:id,name') ->get(['id', 'title', 'slug']); - Filtrar padres + relaciones (whereHas + with). Solo se traen posts que tengan comentarios y luego se cargan los comentarios. Perfecto para filtros “solo con actividad”.
Post::whereHas('comments')->with('comments')->get(); - withWhereHas: Filtra los posts que tienen comentarios aprobados y carga solo esos comentarios. Una sola consulta de filtro + eager loading.
Post::withWhereHas('comments', fn($q) => $q->approved())->get(); - Polymorphic Eager Loading (Para relaciones polimórficas): Ideal para feeds de actividad donde un “subject” puede ser Post, Video, Comment, etc.
Activity::with(['subject' => function ($morph) { $morph->morphWith([ Post::class => ['category'], Video::class => ['tags'], ]); }])->get(); - Agregados con relaciones (withCount, withSum, withAvg, etc.)
Ahora cada post tiene "$post->comments_count" y "$post->comments_sum_votes". Sin consultas extra.Post::withCount('comments') ->withSum('comments', 'votes') ->get(); - Alias en agregados (nombres personalizados).
En vez de "comments_count" se obtiene "approved_comments_count".Post::withCount([ 'comments as approved_comments_count' => fn($q) => $q->approved() ]) ->get(); - Conditional Eager Loading (carga según condición).
Perfecto para APIs con parámetros ?with=comments o para dashboards donde a veces quieres todo y a veces solo lo básico.Post::when($request->includeComments, fn($q) => $q->with('comments'))->get(); - Default Eager Loading (en el modelo): En el modelo "Post.php", por ejemplo:
Cada vez que se use Post::all() o Post::find(), Laravel cargará automáticamente estas relaciones. Ideal para modelos principales de la app.protected $with = ['category', 'author']; - Evitar el Lazy Loading en desarrollo: Agregar esto en tu "AppServiceProvider" o en un modelo base:
use Illuminate\Database\Eloquent\Model; Model::preventLazyLoading(!app()->isProduction());