¿Cómo pasar datos a todas las vistas en Laravel 5?

125

Quiero tener algunos datos predeterminados accesibles en todas las vistas en mi aplicación Laravel 5.

Intenté buscarlo, pero solo encontré resultados para Laravel 4. He leído la documentación 'Compartir datos con todas las vistas' aquí, pero no puedo entender qué hacer. ¿Dónde se debe colocar el siguiente código?

View::share('data', [1, 2, 3]);

Gracias por tu ayuda.

Ragnarsson
fuente
bueno, ¿necesitas un código de inicio para gestionar este requisito?
Safoor Safdar
1
si usa View :: share en un proveedor de servicios con los resultados de una llamada a la base de datos, la aplicación generará un error al ejecutar una migración de actualización de DB o al intentar ejecutar dusk con una conexión de db inalcanzable (historia larga, .env.dusk.local es se usa solo después de ejecutar el proveedor de servicios). Como se menciona a continuación en un controlador base o middlware es lo mejor.
Andy Lobel
También tenga cuidado cuando lo use *en compositores de vistas, especialmente si usa consultas db, ya que se ejecuta para cada sub vista, componente, etc. incluido, para que pueda terminar ejecutando cientos de consultas innecesarias, lo mejor es usar la vista base, por ejemplo, diseños. la aplicación luego pasa los datos según sea necesario.
Andy Lobel

Respuestas:

221

Este objetivo se puede lograr a través de diferentes métodos,

1. Usando BaseController

De la forma en que me gusta configurar las cosas, hago una BaseControllerclase que amplía la de Laravel Controllery establezco varias cosas globales allí. Todos los demás controladores se extienden desde BaseControllerel controlador de Laravel en lugar de hacerlo.

class BaseController extends Controller
{
  public function __construct()
  {
    //its just a dummy data object.
    $user = User::all();

    // Sharing is caring
    View::share('user', $user);
  }
}

2. Usando filtro

Si sabe con certeza que desea configurar algo para las vistas en cada solicitud en toda la aplicación, también puede hacerlo a través de un filtro que se ejecuta antes de la solicitud; así es como trato con el objeto Usuario en Laravel.

App::before(function($request)
{
  // Set up global user object for views
  View::share('user', User::all());
});

O

Puedes definir tu propio filtro

Route::filter('user-filter', function() {
    View::share('user', User::all());
});

y llamarlo a través de una simple llamada de filtro.

Actualización según la versión 5. *

3. Usando Middleware

Usando el View::shareconmiddleware

Route::group(['middleware' => 'SomeMiddleware'], function(){
  // routes
});



class SomeMiddleware {
  public function handle($request)
  {
    \View::share('user', auth()->user());
  }
}

4. Usando View Composer

View Composer también ayuda a enlazar datos específicos para ver de diferentes maneras. Puede vincular directamente la variable a una vista específica o a todas las vistas. Por ejemplo, puede crear su propio directorio para almacenar su archivo de composición de vista de acuerdo con los requisitos. y estos archivos de composición de vista a través del Servicio proporcionan interactuar con la vista.

El método Ver compositor puede usarse de manera diferente. El primer ejemplo puede parecerse:

Podrías crear un App\Http\ViewComposersdirectorio.

Proveedor de servicio

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
    public function boot() {
        view()->composer("ViewName","App\Http\ViewComposers\TestViewComposer");
    }
}

Después de eso, agregue este proveedor a config / app.php en la sección "proveedores".

TestViewComposer

namespace App\Http\ViewComposers;

use Illuminate\Contracts\View\View;

class TestViewComposer {

    public function compose(View $view) {
        $view->with('ViewComposerTestVariable', "Calling with View Composer Provider");
    }
}

ViewName.blade.php

Here you are... {{$ViewComposerTestVariable}}

Este método podría ayudar solo para una vista específica. Pero si desea activar ViewComposer para todas las vistas, tenemos que aplicar este cambio único a ServiceProvider.

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
    public function boot() {
        view()->composer('*',"App\Http\ViewComposers\TestViewComposer");
    }
}

Referencia

Documentación Laravel

Para mayor aclaración Episodio de Laracast

Si todavía hay algo poco claro de mi parte, avíseme.

Safoor Safdar
fuente
Su ejemplo no tiene el register()método - no es opcional
Jonathan
@ Jonathan, gracias por señalarlo, pero el ejemplo contiene solo aquellas secciones que deben cuidarse. perspectiva para compartir datos con la vista.
Safoor Safdar
donde pones el filtro probablemente la respuesta más correcta ahora es usar grupos de middleware laravel.com/docs/5.3/middleware#middleware-groups o middleware global
Toskan
77
Esta no es una buena idea, Ver compositores crea la instancia de compositor para cada vista individual, lo que significa que si ejecuta un bucle de 1000 veces, se crearían 1000 instancias de compositor y, 1000 veces se maneja el evento de disparo, que no es algo que desee.
Reza Shadman
44
@RezaShadman es correcto! Aprendí esto de la manera difícil. Mi aplicación funcionaba muy lentamente hasta que instalé la herramienta laravel-debugbar para investigar. Luego me di cuenta de que las 8 consultas se ejecutaban aproximadamente 15 veces para una sola carga de página. Esto se debe a que se llamará al compositor de vistas para cada archivo Blade que se incluya. Eso es si está utilizando el asterisco *. Si no está utilizando el, *entonces debería estar bien.
Syclone
66

Puede crear su propio proveedor de servicios (el ViewServiceProvidernombre es común) o puede usar el existente AppServiceProvider.

En su proveedor seleccionado, ponga su código en el método de arranque.

public function boot() {
    view()->share('data', [1, 2, 3]);
}

Esto hará un $data variable sea accesible en todas sus vistas.

Si en vez desee utilizar la fachada en lugar del ayudante, el cambio view()->a View::pero no se olvide de tener use View;en la parte superior de su archivo.

Marwelln
fuente
Gracias, trabajando muy bien. ¿La función de arranque está pensada para este tipo de cosas o recomienda crear mi propio proveedor de servicios?
Ragnarsson
2
Si solo tiene una o dos cosas para compartir, AppServiceProviderestá bien, pero si tiene algo más que eso, debería considerar crear un nuevo proveedor.
Marwelln
¡Estaba funcionando pero solo veo que no está funcionando hoy! usando composer updatetambién no funciona. En realidad no está disparando boot()en absoluto. Necesito compartir dos variables.
itsazzad
11
Tenga en cuenta que esto no funcionará si obtiene registros de la base de datos, ya que se llamará antes de ejecutar las migraciones. Entonces, básicamente, está tratando de recuperar registros de la base de datos antes de que existan. Al menos ese parece ser el caso para mí.
lorey
1
Desafortunadamente, esto no parece funcionar con compartir un usuario conectado Auth :: user (), la respuesta # 1 de Safoor, debajo de esta, sí :)
Stan Smulders
11

Encontré que este es el más fácil. Cree un nuevo proveedor y use el '*'comodín para adjuntarlo a todas las vistas. Funciona en 5.3 también :-)

<?php

namespace App\Providers;

use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;

class ViewServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     * @return void
     */
    public function boot()
    {
        view()->composer('*', function ($view)
        {
            $user = request()->user();

            $view->with('user', $user);
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
Stan Smulders
fuente
2
Agregue este proveedor a la matriz de proveedores en su configuración / aplicación "App \ Providers \ ViewServiceProvider :: class"
Nadeem0035
8

La mejor manera sería compartir la variable usando View::share('var', $value);

Problemas con la composición usando "*":

Considere el siguiente enfoque:

<?php
// from AppServiceProvider::boot()
$viewFactory = $this->app->make(Factory::class);

$viewFacrory->compose('*', GlobalComposer::class);

Desde una vista de hoja de ejemplo:

  @for($i = 0; $i<1000; $i++)
    @include('some_partial_view_to_display_i', ['toDisplay' => $i])
  @endfor

¿Lo que pasa?

  • La GlobalComposerclase se instancia 1000 veces usando App::make.
  • El evento composing:some_partial_view_to_display_ise maneja 1000 veces.
  • La composefunción dentro de la GlobalComposerclase se llama 1000 veces.

Pero la vista parcial some_partial_view_to_display_ino tiene nada que ver con las variables compuestas, GlobalComposerpero aumenta considerablemente el tiempo de renderizado.

Mejor enfoque?

Utilizando a lo View::sharelargo de un middleware agrupado.

Route::group(['middleware' => 'WebMiddleware'], function(){
  // Web routes
});

Route::group(['prefix' => 'api'], function (){

});

class WebMiddleware {
  public function handle($request)
  {
    \View::share('user', auth()->user());
  }
}

Actualizar

Si está utilizando algo que se calcula a través de la tubería de middleware, simplemente puede escuchar el evento adecuado o colocar el middleware de vista compartida en la última parte inferior de la tubería.

Reza Shadman
fuente
4

En la documentación:

Normalmente, realizaría llamadas al método compartido dentro del método de arranque de un proveedor de servicios. Puede agregarlos al AppServiceProvider o generar un proveedor de servicios independiente para alojarlos.

Estoy de acuerdo con Marwelln, solo póngalo AppServiceProvideren la función de arranque:

public function boot() {
    View::share('youVarName', [1, 2, 3]);
}

Recomiendo usar un nombre específico para la variable, para evitar confusiones o errores con otras variables no 'globales'.

Santiago Mendoza Ramirez
fuente
3

La documentación es escuchar https://laravel.com/docs/5.4/views#view-composers pero lo desglosaré

  1. Busque la aplicación de directorio \ Proveedores en el directorio raíz de su aplicación y cree el archivo ComposerServiceProvider.php y copie y pegue el siguiente texto en él y guárdelo.

    <?php
        namespace App\Providers;
        use Illuminate\Support\Facades\View;
        use Illuminate\Support\ServiceProvider;
    
        class ComposerServiceProvider extends ServiceProvider
        {
            /**
            * Register bindings in the container.
            *
            * @return void
            */
        public function boot()
        {
            // Using class based composers...
            View::composer(
                'profile', 'App\Http\ViewComposers\ProfileComposer'
            );
    
            // Using Closure based composers...
            View::composer('dashboard', function ($view) {
                //
            });
        }
    
        /**
        * Register the service provider.
        *
        * @return void
        */
        public function register()
        {
            //
        }
    }
  2. Desde la raíz de su aplicación, abra Config / app.php y busque la sección Proveedores en el archivo y copie y pegue esta 'Aplicación \ Proveedores \ ComposerServiceProvider', a la matriz.

Al hacer esto, hemos creado el proveedor de servicios Composer. Cuando ejecuta su aplicación con la vista Perfil como http: // yourdomain / something / profile , se llama al proveedor de servicios ComposerServiceProvider y se instancia la clase App \ Http \ ViewComposers \ ProfileComposer llamando al método Composer debido al código siguiente dentro del Método de arranque o función.

 // Using class based composers...
 View::composer(
   'profile', 'App\Http\ViewComposers\ProfileComposer'
 );
  1. Si actualiza su aplicación, recibirá un error porque la clase App \ Http \ ViewComposers \ ProfileComposer aún no existe. Ahora vamos a crearlo.

Vaya a la aplicación de ruta de directorio / Http

  • Cree el directorio llamado ViewComposers

  • Cree el archivo ProfileComposer.php .

    class ProfileComposer
    {
        /**
        * The user repository implementation.
        *
        * @var UserRepository
        */
        protected $users;
    
        /**
        * Create a new profile composer.
        *
        * @param  UserRepository  $users
        * @return void
        */
        public function __construct(UserRepository $users)
        {
            // Dependencies automatically resolved by service container...
            $this->users = $users;
        }
    
        /**
        * Bind data to the view.
        *
        * @param  View  $view
        * @return void
        */
        public function compose(View $view)
        {
            $view->with('count', $this->users->count());
        }
    }

Ahora ve a tu vista o en este caso Profile.blade.php y agrega

{{ $count }}

y eso mostrará el recuento de usuarios en la página de perfil.

Para mostrar el recuento en todas las páginas cambie

// Using class based composers...
View::composer(
    'profile', 'App\Http\ViewComposers\ProfileComposer'
);

A

// Using class based composers...
View::composer(
    '*', 'App\Http\ViewComposers\ProfileComposer'
);
Samuel Kwame Antwi
fuente
<? php y aplicación de espacio de nombres \ Http \ ViewComposers; use Illuminate \ Contracts \ View \ View; falta en
ProfileComposer.php
1

Dentro de su carpeta de configuración puede crear un nombre de archivo php, por ejemplo "variable.php" con el contenido a continuación:

<?php

  return [
    'versionNumber' => '122231',
  ];

Ahora dentro de todas las vistas puedes usarlo como

config('variable.versionNumber')
Mehran
fuente
Lo hago de esta manera en algunos casos, porque la información es verdaderamente global y puede acceder desde cualquier lugar. Por esa razón, llamo al archivo de configuración "global.php" y pongo todo lo que quiero que esté accesible en todas las demás partes de mi código. La única limitación es que esto es para datos estáticos y se almacena en caché. No debe usarse de esta manera si tiene datos que cambian constantemente.
eResourcesInc
1

1) En (aplicación \ Proveedores \ AppServiceProvider.php)

// in boot function
       view()->composer('*', function ($view) {
            $data = User::messages();
            $view->with('var_messages',$data);
        });

2) en su modelo de usuario

  public static function messages(){ // this is just example
        $my_id = auth()->user()->id;
        $data= Message::whereTo($my_id)->whereIs_read('0')->get(); 
        return $data; // return is required
    }

3) en tu vista

 {{ $var_messages }}
Abdelhakim Ezzahraoui
fuente
0

Método Laravel 5.6: https://laravel.com/docs/5.6/views#passing-data-to-views

Ejemplo, al compartir una colección de modelos con todas las vistas (AppServiceProvider.php):

use Illuminate\Support\Facades\View;
use App\Product;

public function boot()
{
    $products = Product::all();
    View::share('products', $products);

}
Alexander Kim
fuente
2
Esto causará problemas si está intentando crear una nueva aplicación con una base de datos vacía.
Chris Herbert
0

Tienes dos opciones:

1. Compartir a través de la función de arranque en App \ Providers \ AppServiceProvider

public function boot() { view()->share('key', 'value'); }

Y acceda a la variable $ key en cualquier archivo de vista.

Nota: Recuerde que no puede acceder a los datos actuales de Sesión, Autenticación, Ruta aquí. Esta opción es buena solo si desea compartir datos estáticos. Suponga que desea compartir algunos datos basados ​​en el usuario actual, la ruta o cualquier variable de sesión personalizada que no podrá hacer con esto.

  1. Uso de una clase auxiliar Cree una clase auxiliar en cualquier lugar de su aplicación y regístrela en la matriz Alias ​​en el archivo app.php en la carpeta de configuración.

'aliases' => [ ..., 'Helper' => App\HelperClass\Helper::class, ],

y crea Helper.php en la carpeta HelperClass dentro de la carpeta App

namespace App\HelperClass;

class Helper
{
    public static function Sample()
    {
        //Your Code Here
    }
}

y acceder a él en cualquier lugar como Helper::Sample()

No estará restringido aquí para usar Auth, Route, Session o cualquier otra clase.

Priya Chetwani
fuente