Laravel View Composer y Service Provider
Guía práctica para aprender View Composer en Laravel y registrarlo mediante un Service Provider. Incluye estructura de archivos, código, modelos, migraciones, vistas Blade y un proyecto listo para probar. En Laravel, View Composer y Service Provider suelen aparecer juntos porque el Provider es un lugar ideal para registrar los View Composers.
¿Qué es un View Composer?
¿Qué es un View Composer?
Un View Composer permite ejecutar código automáticamente cada vez que una determinada vista se carga.
Por ejemplo, si varias vistas necesitan mostrar las categorías:
return view('productos.index', [
'categorias' => Categoria::all()
]);
En lugar de pasar $categorias desde cada controlador, puedes usar un View Composer.
View::composer('productos.*', function ($view) {
$view->with('categorias', Categoria::all());
});
Ahora todas las vistas productos.* tendrán disponible:
{{ $categorias }}
¿Qué es un Service Provider?
¿Qué es un Service Provider?
Un Service Provider es el mecanismo de Laravel para registrar/configurar servicios cuando la aplicación se inicia.
Por ejemplo:
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
//
}
public function boot(): void
{
//
}
}
register()→ registrar servicios/dependencias.boot()→ ejecutar configuración después de que los servicios hayan sido registrados.
Los View Composers normalmente se registran en boot().
View Composer dentro de un Provider
Por ejemplo:
namespace App\Providers;
use Illuminate\Support\Facades\View;
use App\Models\Categoria;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
//
}
public function boot(): void
{
View::composer('productos.*', function ($view) {
$view->with('categorias', Categoria::all());
});
}
}
Entonces:
Request
↓
Laravel
↓
AppServiceProvider::boot()
↓
Registra View Composer
↓
Se carga productos.index
↓
View Composer se ejecuta
↓
$categorias disponible en la vista
También puedes crear una clase Composer
Para lógica más compleja, es mejor separar la lógica:
php artisan make:view-composer ProductComposer
Y luego:
class ProductComposer
{
public function compose(View $view): void
{
$view->with('categorias', Categoria::all());
}
}
En el Provider:
View::composer(
'productos.*',
ProductComposer::class
);
Esto queda mucho más limpio cuando el Composer empieza a crecer.
Ejemplo práctico: menú de categorías
Supongamos que tenemos este modelo:
class Categoria extends Model
{
protected $fillable = ['nombre'];
}
Y queremos que las categorías estén disponibles automáticamente en:
productos.indexproductos.showproductos.create
Sin tener que hacer esto en cada controlador:
$categorias = Categoria::all();
return view('productos.index', compact('categorias'));
1. Creamos el View Composer
Podemos crear una clase:
php artisan make:view-composer CategoriaComposer
La clase podría quedar así:
namespace App\View\Composers;
use App\Models\Categoria;
use Illuminate\View\View;
class CategoriaComposer
{
public function compose(View $view): void
{
$categorias = Categoria::orderBy('nombre')->get();
$view->with('categorias', $categorias);
}
}
El método compose() se ejecutará cuando se cargue la vista asociada.
2. Lo registramos en el Service Provider
En AppServiceProvider.php:
namespace App\Providers;
use App\View\Composers\CategoriaComposer;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
//
}
public function boot(): void
{
View::composer(
'productos.*',
CategoriaComposer::class
);
}
}
La parte importante es:
View::composer('productos.*', CategoriaComposer::class);
Esto significa:
Cada vez que Laravel cargue una vista cuyo nombre empiece por
productos., ejecutaCategoriaComposer.
3. Usamos $categorias en Blade
Por ejemplo, en:
resources/views/productos/index.blade.php
<h1>Productos</h1>
<ul>
@foreach ($categorias as $categoria)
<li>
{{ $categoria->nombre }}
</li>
@endforeach
</ul>
No necesitamos enviar $categorias desde el controlador.
El controlador puede ser simplemente:
public function index()
{
$productos = Producto::all();
return view('productos.index', compact('productos'));
}
Laravel hará internamente:
Controlador
↓
view('productos.index')
↓
View Composer
↓
CategoriaComposer
↓
obtiene Categoria::orderBy(...)->get()
↓
$categorias
↓
productos.index.blade.php
4. ¿Por qué es útil?
Imagina que tienes 10 controladores que cargan diferentes vistas de productos.
Sin Composer:
// Controlador 1
$categorias = Categoria::all();
// Controlador 2
$categorias = Categoria::all();
// Controlador 3
$categorias = Categoria::all();
// ...
Con View Composer:
View::composer(
'productos.*',
CategoriaComposer::class
);
Y listo. Todas las vistas productos.* reciben automáticamente $categorias.
La estructura mínima del proyecto Laravel
quedaría así:
mi-proyecto/
│
├── app/
│ ├── Models/
│ │ ├── Categoria.php
│ │ └── Producto.php
│ │
│ ├── Providers/
│ │ └── AppServiceProvider.php
│ │
│ └── View/
│ └── Composers/
│ └── CategoriaComposer.php
│
├── resources/
│ └── views/
│ ├── layouts/
│ │ └── app.blade.php
│ │
│ └── productos/
│ ├── index.blade.php
│ ├── show.blade.php
│ └── create.blade.php
│
├── routes/
│ └── web.php
│
├── database/
│ └── migrations/
│ └── xxxx_xx_xx_create_categorias_table.php
│
├── composer.json
└── .env
Archivos principales
app/View/Composers/CategoriaComposer.php
<?php
namespace App\View\Composers;
use App\Models\Categoria;
use Illuminate\View\View;
class CategoriaComposer
{
public function compose(View $view): void
{
$categorias = Categoria::orderBy('nombre')->get();
$view->with('categorias', $categorias);
}
}
app/Providers/AppServiceProvider.php
<?php
namespace App\Providers;
use App\View\Composers\CategoriaComposer;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
//
}
public function boot(): void
{
View::composer(
'productos.*',
CategoriaComposer::class
);
}
}
app/Models/Categoria.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Categoria extends Model
{
protected $fillable = [
'nombre',
];
}
resources/views/productos/index.blade.php
<h1>Productos</h1>
<ul>
@foreach ($categorias as $categoria)
<li>{{ $categoria->nombre }}</li>
@endforeach
</ul>
routes/web.php
use Illuminate\Support\Facades\Route;
Route::view('/productos', 'productos.index');
La relación importante es:
AppServiceProvider
│
│ registra
▼
CategoriaComposer
│
│ proporciona $categorias
▼
productos/*.blade.php
Recurso del Tutorial
GratisTutoriales Recomendados
Sigue explorando publicaciones de la misma categoría