Blog / Laravel / Compositores de vistas (ViewComposers)
Laravel dispone de los ViewComposers para compartir datos concretos con todas o algunas vistas seleccionadas.
Laravel dispone de los ViewComposers para compartir datos concretos con todas o algunas vistas seleccionadas.
Si un dato se va a usar en un template del layout* que se va a repetir en varias, o en todas las vistas, "podemos" usar ViewComposers para tenerlo disponible, ya que las distintas páginas dependen de diferentes controladores.
* Me refiero a "layout" como el template principal en una estructura de vistas, que se usará para cargar partes comunes y el contenido de cada página de esta estructura.
Como ejemplo, tengo mi listado de etiquetas
(Conocimientos y aptitudes), dentro de un elemento
aside
que cargo en todas las páginas públicas de este sitio.
Al usar un ViewComposer trabajo con los datos contenidos en una variable en el template, "nav.blade.php" que carga mi template principal o layout.
Entonces, he usado una variable, una sólo vez y en un sólo template, independiente de un controlador determinado a la hora de obtener los datos que necesita. En realidad, ese template se usa para devolver una parte de la vista en cada una de las peticiones que se hacen en esta web para obtener una vista.
Parece muy complicado, resumiendo: cargamos unos datos en la aplicación antes que las vistas y hacemos que están puedan usarlos, con el mecanismo que nos provee Laravel.
El uso de ViewComposers pasa por los providers que son el mecanismo de Laravel para cargar clases y extender lo que viene de serie después de la instalación.
Primero, vamos a compartir un dato con todas las vistas, sin "crear" el ViewComposer. Este método es aceptable, para cosas muy sencillas.
Quiero tener acceso rápido a la URL actual en la vista en que estoy trabajando. Habitualmente llamaría a:
\Request::url()
en la vista, en el ejemplo voy a encapsular esta llamada en la variable $url.
Abrimos "app/Providers/AppServiceProvider" y añadimos dentro del método boot():
// Share directly $url with all pages
view()->share('url', \Request::url());
Ahora disponemos del contenido que devuelve
Request::url()
en cualquier vista sólo con usar la variable $url.
Vayamos un poco más allá, creemos el composer.
Con el ViewComposer, podemos filtrar las vistas que tienen acceso a la variable.
No hay comando php artisan make:composer XxxComposer. Hay que crear manualmente la clase y para nuestro primer ViewComposer también el directorio. Al final tendremos, por ejemplo: "app/Views/Composers/RoutesComposer.php".
Código del fichero:
<?php
namespace App\Http\Views\Composers;
use Illuminate\Contracts\View\View;
class RoutesComposer
{
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function compose(View $view)
{
$view->with(
'url',
\Request::url()
);
}
}
La clase sólo "compone" y devuelve el dato, el filtrado de vistas es responsabilidad del provider.
En "app/Providers/AppServiceProvider" sustituimos el código anterior del método boot() por la "llamada" al composer he indicamos que estará disponible para todas las vistas, usando un asterisco como comodín.
view()->composer(
'*',
'App\Views\Composers\RoutesComposer'
);
Ahora debemos limpiar las vistas compiladas y regenerar el mapeado de carga de clases:
php artisan view:clear
composer dump-autoload
Las vistas no hay que tocarlas, todo sigue funcionando como al principio.
Un paso más, liberar AppServiceProvider y añadir un service provider para los ViewComposers.
php artisan make:provider ViewComposersProvider
Lo registramos en la configuración: "config/app.php", en el grupo de service providers.
'providers' => [
...
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\ViewComposersProvider::class,
],
Vamos al método boot() de AppServiceProvider y movemos el contenido que pusimos antes, al mismo método del nuevo service provider.
Guardamos todo.
Regenerar el autoload:
composer dump-autoload
Ahora, queda cargar alguna de las páginas que usan la variable $url para ver si todo está funcionando.
15-11-2020