Jak przekazać dane do wszystkich widoków w Laravel 5?

125

Chcę, aby niektóre domyślne dane były dostępne we wszystkich widokach w mojej aplikacji Laravel 5.

Próbowałem go wyszukać, ale znalazłem tylko wyniki dla Laravel 4. Przeczytałem tutaj dokumentację „Udostępnianie danych ze wszystkimi widokami” , ale nie rozumiem, co robić. Gdzie należy umieścić poniższy kod?

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

Dzięki za pomoc.

Ragnarsson
źródło
potrzebujesz kodu startowego, aby zarządzać tym wymaganiem?
Safoor Safdar
1
Heads up przy użyciu View :: share u dostawcy usług z wynikami wywołania bazy danych spowoduje błąd aplikacji podczas uruchamiania odświeżania migracji bazy danych lub próby uruchomienia zmierzchu z nieosiągalnym połączeniem z bazą danych (długa historia, .env.dusk.local to używany tylko po uruchomieniu usługodawcy). Jak wspomniano poniżej, w podstawowym kontrolerze lub oprogramowaniu pośrednim jest najlepszy.
Andy Lobel
Zachowaj ostrożność podczas korzystania *z kompozytorów w widoku, zwłaszcza jeśli używasz zapytań db, ponieważ jest on uruchamiany dla każdego dołączonego widoku podrzędnego, komponentu itp., Abyś mógł uruchomić setki niepotrzebnych zapytań, najlepiej jest użyć widoku podstawowego, np. Układów. app, a następnie w razie potrzeby przekaż dane.
Andy Lobel

Odpowiedzi:

222

Cel ten można osiągnąć różnymi metodami,

1. Korzystanie z BaseController

Sposób, w jaki lubię to konfigurować, BaseControllertworzę klasę, która rozszerza klasę Laravela Controlleri konfiguruję tam różne globalne rzeczy. Wszystkie inne kontrolery następnie pochodzą z kontrolera BaseControllerzamiast Laravel.

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

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

2. Korzystanie z filtra

Jeśli wiesz na pewno, że chcesz coś ustawiać dla widoków na każde żądanie w całej aplikacji, możesz to również zrobić za pomocą filtru, który działa przed żądaniem - tak mam do czynienia z obiektem User w Laravel.

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

LUB

Możesz zdefiniować własny filtr

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

i wywołaj to za pomocą prostego wywołania filtra.

Aktualizacja zgodnie z wersją 5. *

3. Korzystanie z oprogramowania pośredniego

Korzystanie z View::sharewithmiddleware

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



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

4. Korzystanie z programu View Composer

View Composer pomaga również w wiązaniu określonych danych do wyświetlania na różne sposoby. Możesz bezpośrednio powiązać zmienną z określonym widokiem lub wszystkimi widokami. Na przykład możesz utworzyć własny katalog do przechowywania pliku kompozytora widoku zgodnie z wymaganiami. a te widok pliku kompozytora za pośrednictwem usługi zapewniają interakcję z widokiem.

Zobacz metodę kompozytora można użyć w inny sposób, pierwszy przykład może wyglądać podobnie:

Możesz stworzyć App\Http\ViewComposerskatalog.

Dostawca usługi

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

Następnie dodaj tego dostawcę do config / app.php w sekcji „dostawcy”.

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

Ta metoda może pomóc tylko w przypadku określonego widoku. Ale jeśli chcesz wyzwolić ViewComposer do wszystkich widoków, musimy zastosować tę pojedynczą zmianę do ServiceProvider.

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

Odniesienie

Dokumentacja Laravel

Dalsze wyjaśnienia - odcinek Laracast

Jeśli nadal coś jest niejasne z mojej strony, daj mi znać.

Safoor Safdar
źródło
W Twoim przykładzie brakuje register()metody - nie jest opcjonalna
Jonathan
@jonathan dzięki, aby to wskazać, ale przykład zawiera tylko te sekcje, którymi należy się zająć. perspektywę udostępniania danych z widokiem.
Safoor Safdar
gdzie wkładasz filtr? prawdopodobnie najbardziej poprawną odpowiedzią jest teraz użycie grup oprogramowania pośredniego laravel.com/docs/5.3/middleware#middleware-groups lub globalnego oprogramowania pośredniego
Toskan
7
To nie jest dobry pomysł, widok kompozytorów tworzy instancję kompozytora dla każdego widoku, co oznacza, że ​​jeśli uruchomisz pętlę 1000 razy, zostanie utworzonych 1000 instancji kompozytora i 1000 razy zostanie obsłużone zdarzenie wypalenia, co nie jest czymś, czego chcesz.
Reza Shadman
4
@RezaShadman ma rację! Nauczyłem się tego na własnej skórze. Moja aplikacja działała tak wolno, dopóki nie zainstalowałem narzędzia laravel-debugbar w celu zbadania sprawy. Potem zdałem sobie sprawę, że wszystkie 8 zapytań były wykonywane około 15 razy przy ładowaniu pojedynczej strony. Dzieje się tak, ponieważ kompozytor widoku będzie wywoływany dla każdego dołączonego pliku kasetowego. To znaczy, jeśli używasz gwiazdki *. Jeśli nie używasz, *wszystko powinno być w porządku.
Syclone
66

Możesz utworzyć własnego usługodawcę ( ViewServiceProvidernazwa jest powszechna) lub skorzystać z istniejącego AppServiceProvider.

W wybranym dostawcy umieść kod w metodzie rozruchu.

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

Dzięki temu $datazmienna będzie dostępna we wszystkich widokach.

Jeśli wolisz używać elewacji zamiast pomocnika, zmień view()->ją, View::ale nie zapomnij umieścić jej use View;na początku pliku.

Marwelln
źródło
Dzięki, działa świetnie. Czy funkcja rozruchu jest przeznaczona do tego rodzaju rzeczy, czy może zalecamy utworzenie własnego dostawcy usług?
Ragnarsson,
2
Jeśli masz tylko jedną lub dwie rzeczy do udostępnienia, umieszczenie ich AppServiceProviderjest w porządku, ale jeśli masz coś więcej, powinieneś rozważyć utworzenie nowego dostawcy.
Marwelln,
Działało, ale widzę, że dzisiaj nie działa! używanie composer updaterównież nie działa. Właściwie to wcale nie odpala boot(). Muszę udostępnić dwie zmienne.
itsazzad
11
Należy pamiętać, że to nie zadziała, jeśli pobierasz rekordy bazy danych, ponieważ zostanie to wywołane przed wykonaniem migracji. Więc zasadniczo próbujesz pobrać rekordy bazy danych, zanim one istnieją. Przynajmniej tak mi się wydaje.
lorey
1
Niestety to nie wydają się działać z dzielące zalogowany użytkownik :: Auth użytkownika (), Safoor za # 1 odpowiedź poniżej tego jednego, robi :)
Stan Smulders
11

Okazało się, że jest to najłatwiejsze. Utwórz nowego dostawcę i '*'użyj symbolu wieloznacznego, aby dołączyć go do wszystkich widoków. Działa również w 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
źródło
2
Dodaj tego dostawcę do tablicy dostawców w swojej konfiguracji / aplikacji „App \ Providers \ ViewServiceProvider :: class”
Nadeem0035
8

Najlepszym sposobem byłoby udostępnienie zmiennej za pomocą View::share('var', $value);

Problemy z komponowaniem przy użyciu "*":

Rozważ następujące podejście:

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

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

Z przykładowego widoku ostrza:

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

Co się dzieje?

  • GlobalComposerKlasy jest tworzony 1000 razy użyciu App::make.
  • Wydarzenie composing:some_partial_view_to_display_ijest obsługiwane 1000 razy.
  • composeFunkcji wewnątrz GlobalComposerklasy nazywa się 1000 razy.

Ale widok częściowy some_partial_view_to_display_inie ma nic wspólnego ze zmiennymi składającymi się z, GlobalComposerale znacznie wydłuża czas renderowania.

Najlepsze podejście?

Korzystanie View::sharez zgrupowanego oprogramowania pośredniego.

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

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

});

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

Aktualizacja

Jeśli używasz czegoś, co jest obliczane za pośrednictwem potoku oprogramowania pośredniego, możesz po prostu nasłuchiwać odpowiedniego zdarzenia lub umieścić oprogramowanie pośredniczące udziału widoku na ostatnim dole potoku.

Reza Shadman
źródło
4

W dokumentacji:

Zazwyczaj wywołanie metody udostępniania jest wykonywane w ramach metody rozruchu dostawcy usług. Możesz dodać je do AppServiceProvider lub wygenerować oddzielnego dostawcę usług, aby je pomieścić.

Zgadzam się z Marwellnem, po prostu wstaw to w AppServiceProviderfunkcji rozruchu:

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

Zalecam użycie określonej nazwy zmiennej, aby uniknąć nieporozumień lub błędów z innymi zmiennymi nie „globalnymi”.

Santiago Mendoza Ramirez
źródło
3

Dokumentację słychać https://laravel.com/docs/5.4/views#view-composers, ale ja ją rozbiję

  1. Poszukaj katalogu app \ Providers w katalogu głównym swojej aplikacji i utwórz plik ComposerServiceProvider.php, a następnie skopiuj i wklej poniższy tekst do niego i zapisz go.

    <?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. Z katalogu głównego aplikacji otwórz plik Config / app.php i poszukaj sekcji Providers w pliku, a następnie skopiuj i wklej to „App \ Providers \ ComposerServiceProvider” do tablicy.

W ten sposób stworzyliśmy dostawcę usług Composer. Po uruchomieniu aplikacji z widokiem Profil, takim jak http: // twoja_domena / coś / profil , wywoływany jest dostawca usług ComposerServiceProvider, a instancja klasy App \ Http \ ViewComposers \ ProfileComposer jest wywoływana metodą Composer ze względu na poniższy kod w metoda lub funkcja rozruchu.

 // Using class based composers...
 View::composer(
   'profile', 'App\Http\ViewComposers\ProfileComposer'
 );
  1. Jeśli odświeżysz aplikację, pojawi się błąd, ponieważ klasa App \ Http \ ViewComposers \ ProfileComposer jeszcze nie istnieje. Teraz stwórzmy to.

Przejdź do ścieżki katalogu app / Http

  • Utwórz katalog o nazwie ViewComposers

  • Utwórz plik 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());
        }
    }
    

Teraz przejdź do swojego widoku lub w tym przypadku Profile.blade.php i dodaj

{{ $count }}

i to pokaże liczbę użytkowników na stronie profilu.

Aby wyświetlić liczbę na wszystkich stronach, zmień

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

Do

// Using class based composers...
View::composer(
    '*', 'App\Http\ViewComposers\ProfileComposer'
);
Samuel Kwame Antwi
źródło
<? php i przestrzeń nazw App \ Http \ ViewComposers; użyj Illuminate \ Contracts \ View \ View; brakuje na
ProfileComposer.php
1

Wewnątrz folderu konfiguracyjnego możesz utworzyć plik php, nazwij go na przykład „zmienna.php” z zawartością poniżej:

<?php

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

Teraz we wszystkich widokach możesz to wykorzystać

config('variable.versionNumber')
Mehran
źródło
W niektórych przypadkach robię to w ten sposób, ponieważ informacje są naprawdę globalne i możesz uzyskać do nich dostęp z dowolnego miejsca. Z tego powodu nazywam plik konfiguracyjny „global.php” i umieszczam w nim wszystko, co chcę, aby było dostępne we wszystkich innych częściach mojego kodu. Jedynym ograniczeniem jest to, że dotyczy to danych statycznych i jest buforowanych. Nie należy go używać w ten sposób, jeśli masz stale zmieniające się dane.
eResourcesInc
1

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

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

2) w Twoim modelu użytkownika

  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) w Twojej opinii

 {{ $var_messages }}
Abdelhakim Ezzahraoui
źródło
0

Metoda Laravel 5.6: https://laravel.com/docs/5.6/views#passing-data-to-views

Przykład z udostępnieniem kolekcji modeli wszystkim widokom (AppServiceProvider.php):

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

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

}
Alexander Kim
źródło
2
Spowoduje to problemy, jeśli próbujesz utworzyć nową aplikację z pustą bazą danych.
Chris Herbert,
0

Masz dwie możliwości:

1. udostępnij za pomocą funkcji rozruchu w App \ Providers \ AppServiceProvider

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

I uzyskaj dostęp do zmiennej $ key w dowolnym pliku widoku.

Uwaga: pamiętaj, że nie możesz tutaj uzyskać dostępu do danych bieżącej sesji, uwierzytelnienia i trasy. Ta opcja jest dobra tylko wtedy, gdy chcesz udostępniać dane statyczne. Załóżmy, że chcesz udostępnić pewne dane na podstawie bieżącego użytkownika, trasy lub dowolnej niestandardowej zmiennej sesji, której nie będziesz w stanie z tym zrobić.

  1. Użycie klasy pomocniczej Utwórz klasę pomocniczą w dowolnym miejscu aplikacji i zarejestruj ją w tablicy Alias ​​w pliku app.php w folderze konfiguracyjnym.

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

i utwórz plik Helper.php w folderze HelperClass w folderze aplikacji

namespace App\HelperClass;

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

i uzyskaj do niego dostęp w dowolnym miejscu Helper::Sample()

Nie będziesz tutaj ograniczony do korzystania z Auth, Route, Session ani żadnych innych klas.

Priya Chetwani
źródło