Comment transmettre des données à toutes les vues dans Laravel 5?

125

Je souhaite que certaines données par défaut soient accessibles dans toutes les vues de mon application Laravel 5.

J'ai essayé de le rechercher mais je ne trouve que des résultats pour Laravel 4. J'ai lu la documentation «Partage de données avec toutes les vues» ici mais je ne comprends pas quoi faire. Où doit être placé le code suivant?

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

Merci de votre aide.

Ragnarsson
la source
Eh bien, vous avez besoin d'un code de démarrage pour gérer cette exigence?
Safoor Safdar
1
la tête en haut en utilisant View :: share dans un fournisseur de services avec les résultats d'un appel de base de données provoquera une erreur de l'application lors de l'exécution d'une migration de rafraîchissement de la base de données ou en essayant d'exécuter le crépuscule avec une connexion de base de données inaccessible (longue histoire, .env.dusk.local est utilisé uniquement après l'exécution du fournisseur de services). Comme mentionné ci-dessous, un contrôleur de base ou un middlware est le meilleur.
Andy Lobel
Faites également attention lorsque vous utilisez des *compositeurs sur vue, en particulier si vous utilisez des requêtes de base de données, car il est exécuté pour chaque sous-vue, composant, etc. inclus, de sorte que vous pourriez finir par exécuter des centaines de requêtes inutiles, la meilleure chose est d'utiliser la vue de base, par exemple les mises en page. puis transmettez les données au besoin.
Andy Lobel

Réponses:

222

Cet objectif peut atteindre par différentes méthodes,

1. Utilisation de BaseController

La façon dont j'aime mettre les choses en place, je crée une BaseControllerclasse qui étend celle de Laravel Controlleret j'y installe diverses choses globales. Tous les autres contrôleurs s'étendent alors à partir BaseControllerdu contrôleur de Laravel plutôt que du contrôleur.

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

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

2. Utilisation du filtre

Si vous savez pertinemment que vous voulez quelque chose de configuré pour les vues sur chaque demande dans toute l'application, vous pouvez également le faire via un filtre qui s'exécute avant la demande - c'est ainsi que je traite l'objet User dans Laravel.

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

OU

Vous pouvez définir votre propre filtre

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

et appelez-le via un simple appel de filtre.

Mise à jour selon la version 5. *

3. Utilisation du middleware

Utiliser le View::shareavecmiddleware

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



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

4. Utilisation de View Composer

View Composer permet également de lier des données spécifiques à afficher de différentes manières. Vous pouvez directement lier une variable à une vue spécifique ou à toutes les vues. Par exemple, vous pouvez créer votre propre répertoire pour stocker votre fichier de composition de vues en fonction des besoins. et ces fichiers de composition de vues via le service fournissent une interaction avec la vue.

La méthode de composition de vue peut utiliser une manière différente, le premier exemple peut se ressembler:

Vous pouvez créer un App\Http\ViewComposersrépertoire.

Fournisseur de services

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

Après cela, ajoutez ce fournisseur à config / app.php dans la section «fournisseurs».

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}}

Cette méthode pourrait aider uniquement pour une vue spécifique. Mais si vous souhaitez déclencher ViewComposer sur toutes les vues, nous devons appliquer cette seule modification à ServiceProvider.

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

Référence

Documentation Laravel

Pour plus de précisions sur l'épisode Laracast

Si quelque chose n'est toujours pas clair de mon côté, faites-le moi savoir.

Safoor Safdar
la source
Votre exemple manque la register()méthode - ce n'est pas facultatif
Jonathan
@jonathan merci de le signaler, mais l'exemple ne contient que les sections dont il faut s'occuper. perspective de partager des données avec vue.
Safoor Safdar
où mettez-vous le filtre? probablement la réponse la plus correcte est maintenant l'utilisation de groupes de middleware laravel.com/docs/5.3/middleware#middleware-groups ou de middleware global
Toskan
7
Ce n'est pas une bonne idée, les compositeurs de vue créent l'instance de compositeur pour chaque vue individuelle, cela signifie que si vous exécutez une boucle de 1000 fois, 1000 instances de compositeur seront créées et, 1000 fois, l'événement de déclenchement est géré, ce qui n'est pas quelque chose que vous voulez.
Reza Shadman
4
@RezaShadman a raison! J'ai appris cela à la dure. Mon application fonctionnait si lentement que j'ai installé l'outil laravel-debugbar pour enquêter. Ensuite, j'ai réalisé que les 8 requêtes étaient exécutées environ 15 fois pour une seule page de chargement. En effet, le composeur de vue sera appelé pour chaque fichier lame inclus. C'est si vous utilisez l'astérisque *. Si vous n'utilisez pas le, tout *devrait bien se passer.
Syclone
66

Vous pouvez soit créer votre propre fournisseur de services (ViewServiceProvider nom est courant), soit utiliser l'existant AppServiceProvider.

Dans votre fournisseur sélectionné, mettez votre code dans la méthode de démarrage.

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

Cela fera un $data variable accessible dans toutes vos vues.

Si vous préférez utiliser la façade au lieu de l'assistant, changez view()->en View::mais n'oubliez pas d'avoir use View;en haut de votre fichier.

Marwelln
la source
Merci, fonctionne très bien. La fonction de démarrage est-elle destinée à ce genre de chose ou recommandez-vous de créer mon propre fournisseur de services?
Ragnarsson
2
Si vous n'avez qu'une ou deux choses à partager, il AppServiceProvidern'y a pas de problème , mais si vous avez quelque chose de plus que cela, vous devriez envisager de créer un nouveau fournisseur.
Marwelln
Ça fonctionnait mais je vois juste que ça ne marche pas aujourd'hui! en utilisant composer updateégalement ne fonctionne pas. En fait, il ne tire pas du boot()tout. J'ai besoin de partager deux variables.
itsazzad
11
Sachez que cela ne fonctionnera pas si vous récupérez des enregistrements de base de données, car cela sera appelé avant d'exécuter les migrations. Vous essayez donc de récupérer les enregistrements de la base de données avant qu'ils n'existent. Du moins, cela semble être le cas pour moi.
lorey
1
Malheureusement, cela ne semble pas fonctionner avec le partage d'un utilisateur connecté Auth :: user (), la réponse n ° 1 de Safoor, en dessous de celle-ci, fonctionne :)
Stan Smulders
11

J'ai trouvé que c'était le plus simple. Créez un nouveau fournisseur et utilisez le '*'caractère générique pour l'attacher à toutes les vues. Fonctionne également en 5.3 :-)

<?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
la source
2
Ajoutez ce fournisseur dans un tableau de fournisseurs dans votre configuration / application "App \ Providers \ ViewServiceProvider :: class,"
Nadeem0035
8

Le meilleur moyen serait de partager la variable en utilisant View::share('var', $value);

Problèmes de composition avec "*":

Envisagez l'approche suivante:

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

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

À partir d'un exemple de vue de la lame:

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

Ce qui se produit?

  • La GlobalComposerclasse est instanciée 1000 fois en utilisant App::make.
  • L'événement composing:some_partial_view_to_display_iest traité 1000 fois.
  • La composefonction à l'intérieur de la GlobalComposerclasse est appelée 1000 fois.

Mais la vue partielle some_partial_view_to_display_in'a rien à voir avec les variables composées GlobalComposermais augmente considérablement le temps de rendu.

Meilleure approche?

Utilisation View::shareavec un middleware groupé.

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

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

});

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

Mettre à jour

Si vous utilisez quelque chose qui est calculé via le pipeline middleware, vous pouvez simplement écouter l' événement approprié ou placer le middleware de partage de vues au dernier bas du pipeline.

Reza Shadman
la source
4

Dans la documentation:

En règle générale, vous passez des appels à la méthode de partage dans la méthode de démarrage d'un fournisseur de services. Vous êtes libre de les ajouter à AppServiceProvider ou de générer un fournisseur de services distinct pour les héberger.

Je suis d'accord avec Marwelln, il suffit de le mettre AppServiceProviderdans la fonction de démarrage:

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

Je recommande d'utiliser un nom spécifique pour la variable, pour éviter les confusions ou les erreurs avec d'autres variables non «globales».

Santiago Mendoza Ramirez
la source
3

La documentation est entendue https://laravel.com/docs/5.4/views#view-composers mais je vais la décomposer

  1. Recherchez le répertoire app \ Providers dans le répertoire racine de votre application et créez le fichier ComposerServiceProvider.php , copiez et collez le texte ci-dessous et enregistrez-le.

    <?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. À partir de la racine de votre application, ouvrez Config / app.php et recherchez la section Providers dans le fichier et copiez et collez ce 'App \ Providers \ ComposerServiceProvider' dans le tableau.

En faisant cela, nous avons créé le fournisseur de services Composer. Lorsque vous exécutez votre application avec la vue Profile comme http: // votredomaine / quelque chose / profil , le fournisseur de services ComposerServiceProvider est appelé et la classe App \ Http \ ViewComposers \ ProfileComposer est instanciée en appelant la méthode Composer en raison du code ci-dessous dans le méthode ou fonction de démarrage.

 // Using class based composers...
 View::composer(
   'profile', 'App\Http\ViewComposers\ProfileComposer'
 );
  1. Si vous actualisez votre application, vous obtiendrez une erreur car la classe App \ Http \ ViewComposers \ ProfileComposer n'existe pas encore. Maintenant, créons-le.

Accédez au chemin du répertoire app / Http

  • Créez le répertoire appelé ViewComposers

  • Créez le fichier 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());
        }
    }

Maintenant, allez dans votre vue ou dans ce cas Profile.blade.php et ajoutez

{{ $count }}

et cela montrera le nombre d'utilisateurs sur la page de profil.

Pour afficher le décompte sur toutes les pages, changez

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

À

// Using class based composers...
View::composer(
    '*', 'App\Http\ViewComposers\ProfileComposer'
);
Samuel Kwame Antwi
la source
<? php et espace de noms App \ Http \ ViewComposers; utilisez Illuminate \ Contracts \ View \ View; est absent de ProfileComposer.php
Unicco
1

La documentation est ici https://laravel.com/docs/5.4/views#view-composers mais je vais la décomposer 1.Recherchez les fournisseurs d'annuaire dans votre répertoire racine et créez le pour ComposerServiceProvider.php avec le contenu

Samuel Kwame Antwi
la source
1

Dans votre dossier de configuration, vous pouvez créer un nom de fichier php, par exemple "variable.php" avec le contenu ci-dessous:

<?php

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

Maintenant, dans toutes les vues, vous pouvez l'utiliser comme

config('variable.versionNumber')
Mehran
la source
Je le fais de cette façon dans certains cas, car les informations sont vraiment mondiales et vous pouvez y accéder de n'importe où. Pour cette raison, j'appelle le fichier de configuration "global.php" et j'y mets tout ce que je souhaite rendre accessible dans toutes les autres parties de mon code. La seule limitation est que cela concerne les données statiques et est mis en cache. Il ne devrait pas être utilisé de cette façon si vous avez des données en constante évolution.
eResourcesInc
1

1) Dans (app \ Providers \ AppServiceProvider.php)

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

2) dans votre modèle d'utilisateur

  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) dans votre vue

 {{ $var_messages }}
Abdelhakim Ezzahraoui
la source
0

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

Exemple, avec le partage d'une collection de modèles avec toutes les vues (AppServiceProvider.php):

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

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

}
Alexandre Kim
la source
2
Cela causera des problèmes si vous essayez de créer une nouvelle application avec une base de données vide.
Chris Herbert
0

Vous avez deux options:

1.Partagez via la fonction de démarrage dans App \ Providers \ AppServiceProvider

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

Et accédez à la variable $ key dans n'importe quel fichier de vue.

Remarque: n'oubliez pas que vous ne pouvez pas accéder aux données de session, d'authentification et d'itinéraire en cours ici. Cette option n'est utile que si vous souhaitez partager des données statiques. Supposons que vous souhaitiez partager des données en fonction de l'utilisateur actuel, de l'itinéraire ou de toute variable de session personnalisée que vous ne pourrez pas faire avec cela.

  1. Utilisation d'une classe d'assistance Créez une classe d'assistance n'importe où dans votre application et enregistrez-la dans le tableau Alias ​​du fichier app.php du dossier config.

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

et créez Helper.php dans le dossier HelperClass dans le dossier App

namespace App\HelperClass;

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

et accédez-y partout comme Helper::Sample()

Vous ne serez pas limité ici pour utiliser Auth, Route, Session ou toute autre classe.

Priya Chetwani
la source