Bagaimana cara mengirimkan data ke semua tampilan di Laravel 5?

125

Saya ingin memiliki beberapa data default yang dapat diakses di semua tampilan di aplikasi Laravel 5 saya.

Saya telah mencoba mencarinya tetapi hanya menemukan hasil untuk Laravel 4. Saya telah membaca dokumentasi 'Berbagi Data Dengan Semua Tampilan' di sini tetapi saya tidak dapat memahami apa yang harus dilakukan. Di mana kode berikut harus ditempatkan?

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

Terima kasih atas bantuan Anda.

Ragnarsson
sumber
Nah, Anda memerlukan kode startup untuk mengelola persyaratan ini?
Safoor Safdar
1
kepala up menggunakan View :: share di penyedia layanan dengan hasil panggilan database akan membuat kesalahan aplikasi saat menjalankan migrasi db refresh atau mencoba menjalankan senja dengan koneksi db tidak terjangkau (cerita panjang, .env.dusk.local is hanya digunakan setelah penyedia layanan dijalankan). Seperti disebutkan di bawah ini, pengontrol dasar atau middlware adalah yang terbaik.
Andy Lobel
Juga berhati-hatilah saat menggunakan pembuat *on view terutama jika menggunakan query db, karena dijalankan untuk setiap sub view, komponen, dll, sehingga Anda bisa saja menjalankan ratusan query yang tidak perlu, hal terbaik adalah menggunakan tampilan dasar misalnya layout. aplikasi kemudian meneruskan data sesuai kebutuhan.
Andy Lobel

Jawaban:

222

Target ini dapat dicapai melalui metode yang berbeda,

1. Menggunakan BaseController

Cara saya suka mengatur sesuatu, saya membuat BaseControllerkelas yang memperluas milik Laravel Controller, dan mengatur berbagai hal global di sana. Semua pengontrol lain kemudian diperluas dari BaseControlleralih-alih Pengontrol 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. Menggunakan Filter

Jika Anda mengetahui fakta bahwa Anda menginginkan sesuatu yang diatur untuk tampilan pada setiap permintaan di seluruh aplikasi, Anda juga dapat melakukannya melalui filter yang berjalan sebelum permintaan - inilah cara saya menangani objek Pengguna di Laravel.

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

ATAU

Anda dapat menentukan filter Anda sendiri

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

dan menyebutnya melalui panggilan filter sederhana.

Perbarui Menurut Versi 5. *

3. Menggunakan Middleware

Menggunakan View::sharedenganmiddleware

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



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

4. Menggunakan View Composer

View Composer juga membantu mengikat data tertentu untuk dilihat dengan cara yang berbeda. Anda dapat langsung mengikat variabel ke tampilan tertentu atau ke semua tampilan. Sebagai Contoh, Anda dapat membuat direktori Anda sendiri untuk menyimpan file penulis tampilan Anda sesuai dengan kebutuhan. dan file penulis tampilan ini melalui Layanan menyediakan interaksi dengan tampilan.

Metode tampilan komposer dapat menggunakan cara yang berbeda, Contoh pertama dapat terlihat sama:

Anda bisa membuat App\Http\ViewComposersdirektori.

Penyedia layanan

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

Setelah itu, tambahkan provider ini ke config / app.php di bawah bagian "provider".

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

Metode ini dapat membantu hanya untuk Tampilan tertentu. Tetapi jika Anda ingin memicu ViewComposer ke semua tampilan, kita harus menerapkan perubahan tunggal ini ke ServiceProvider.

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

Referensi

Dokumentasi Laravel

Untuk Klarifikasi Lebih Lanjut Episode Laracast

Jika masih ada sesuatu yang tidak jelas dari sisi saya, beri tahu saya.

Safoor Safdar
sumber
Contoh Anda tidak memiliki register()metode - ini bukan opsional
Jonathan
@jonathan terima kasih untuk menunjukkannya, tetapi contoh hanya berisi bagian yang perlu dijaga. perspektif untuk berbagi data dengan tampilan.
Safoor Safdar
di mana Anda meletakkan filter? mungkin jawaban yang paling benar sekarang menggunakan grup middleware laravel.com/docs/5.3/middleware#middleware-groups atau global middleware
Toskan
7
Ini bukan ide yang baik, View composer membuat instance komposer untuk setiap tampilan individual. Artinya jika Anda menjalankan loop 1000 kali, 1000 instance komposer akan dibuat, dan 1000 kali event pengaktifan ditangani yang bukan merupakan sesuatu yang Anda inginkan.
Reza Shadman
4
@RezaShadman benar! Saya belajar ini dengan cara yang sulit. Aplikasi saya berjalan sangat lambat sampai saya menginstal alat laravel-debugbar untuk menyelidiki. Kemudian saya menyadari bahwa semua 8 kueri dieksekusi sekitar 15 kali untuk satu pemuatan halaman. Ini karena komposer tampilan akan dipanggil untuk setiap file blade yang disertakan. Itu jika Anda menggunakan tanda bintang *. Jika Anda tidak menggunakan *maka Anda akan baik-baik saja.
Syclone
66

Anda dapat membuat penyedia layanan Anda sendiri ( ViewServiceProvidernamanya biasa) atau menggunakan yang sudah ada AppServiceProvider.

Di penyedia yang Anda pilih, masukkan kode Anda ke dalam metode boot.

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

Ini akan membuat $datavariabel dapat diakses di semua tampilan Anda.

Jika Anda lebih suka menggunakan fasad daripada helper, ubah view()->ke View::tetapi jangan lupa untuk memiliki use View;di bagian atas file Anda.

Marwelln
sumber
Terima kasih, bekerja dengan baik. Apakah fungsi boot dimaksudkan untuk hal semacam ini atau apakah Anda menyarankan untuk membuat penyedia layanan saya sendiri?
Ragnarsson
2
Jika Anda hanya memiliki satu atau dua hal untuk dibagikan tidak AppServiceProvidermasalah, tetapi jika Anda memiliki sesuatu yang lebih dari itu, Anda harus mempertimbangkan untuk membuat penyedia baru.
Marwelln
Itu berfungsi tetapi saya hanya melihat bahwa itu tidak berfungsi hari ini! menggunakan composer updatejuga tidak berfungsi. Sebenarnya itu tidak menembak boot()sama sekali. Saya perlu membagi dua variabel.
itsazzad
11
Ketahuilah bahwa ini tidak akan berfungsi jika Anda mengambil record database karena ini akan dipanggil sebelum menjalankan migrasi. Jadi pada dasarnya Anda mencoba mengambil rekaman database sebelum ada. Setidaknya itu yang terjadi pada saya.
lorey
1
Sayangnya ini tampaknya tidak berhasil dengan berbagi pengguna yang masuk Auth :: user (), jawaban # 1 Safoor, di bawah ini, tidak :)
Stan Smulders
11

Saya menemukan ini sebagai yang termudah. Buat penyedia baru dan '*'gunakan karakter pengganti untuk melampirkannya ke semua tampilan. Bekerja di 5.3 juga :-)

<?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
sumber
2
Tambahkan penyedia ini ke dalam berbagai penyedia di config / app "App \ Providers \ ViewServiceProvider :: class",
Nadeem0035
8

Cara terbaik adalah membagikan variabel menggunakan View::share('var', $value);

Masalah dengan menulis menggunakan "*":

Pertimbangkan pendekatan berikut:

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

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

Dari contoh tampilan pisau:

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

Apa yang terjadi?

  • The GlobalComposerkelas instantiated 1000 kali menggunakan App::make.
  • Acara composing:some_partial_view_to_display_itersebut ditangani 1000 kali.
  • The composefungsi di dalam GlobalComposerkelas disebut 1000 kali.

Namun tampilan parsial some_partial_view_to_display_itidak ada hubungannya dengan variabel yang disusun oleh GlobalComposertetapi sangat meningkatkan waktu render.

Pendekatan terbaik?

Menggunakan View::sharebersama middleware yang dikelompokkan.

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

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

});

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

Memperbarui

Jika Anda menggunakan sesuatu yang dihitung melalui pipeline middleware, Anda dapat dengan mudah mendengarkan acara yang sesuai atau meletakkan middleware view share di bagian bawah terakhir pipeline.

Reza Shadman
sumber
4

Dalam dokumentasi:

Biasanya, Anda akan melakukan panggilan ke metode berbagi dalam metode booting penyedia layanan. Anda bebas menambahkannya ke AppServiceProvider atau membuat penyedia layanan terpisah untuk menampungnya.

Saya setuju dengan Marwelln, cukup masukkan ke dalam AppServiceProviderfungsi boot:

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

Saya merekomendasikan menggunakan nama tertentu untuk variabel, untuk menghindari kebingungan atau kesalahan dengan variabel lain yang tidak 'global'.

Santiago Mendoza Ramirez
sumber
3

Dokumentasi didengarkan https://laravel.com/docs/5.4/views#view-composers tetapi saya akan memecahnya

  1. Cari aplikasi direktori \ Providers di direktori root aplikasi Anda dan buat file ComposerServiceProvider.php dan salin dan tempel teks di bawah ini ke dalamnya dan simpan.

    <?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. Dari root aplikasi Anda, buka Config / app.php dan cari bagian Providers di file tersebut dan salin dan tempel 'App \ Providers \ ComposerServiceProvider' ini, ke array.

Dengan melakukan ini, kami telah membuat Penyedia Layanan Komposer. Saat Anda menjalankan aplikasi dengan tampilan Profil seperti http: // domainanda / sesuatu / profil , penyedia layanan ComposerServiceProvider dipanggil dan kelas App \ Http \ ViewComposers \ ProfileComposer dibuat memanggil metode Composer karena kode di bawah ini di dalam metode atau fungsi boot.

 // Using class based composers...
 View::composer(
   'profile', 'App\Http\ViewComposers\ProfileComposer'
 );
  1. Jika Anda menyegarkan aplikasi Anda, Anda akan mendapatkan kesalahan karena kelas App \ Http \ ViewComposers \ ProfileComposer belum ada. Sekarang mari kita membuatnya.

Buka aplikasi jalur direktori / Http

  • Buat direktori bernama ViewComposers

  • Buat file 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());
        }
    }

Sekarang masuk ke tampilan Anda atau dalam hal ini Profile.blade.php dan tambahkan

{{ $count }}

dan itu akan menunjukkan jumlah pengguna di halaman profil.

Untuk menunjukkan hitungan di semua halaman berubah

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

Untuk

// Using class based composers...
View::composer(
    '*', 'App\Http\ViewComposers\ProfileComposer'
);
Samuel Kwame Antwi
sumber
<? php dan namespace App \ Http \ ViewComposers; gunakan Illuminate \ Contracts \ View \ View; hilang dari ProfileComposer.php
Unicco
1

Dokumentasi ada di sini https://laravel.com/docs/5.4/views#view-composers tetapi saya akan memecahnya 1. Cari penyedia direktori di direktori root Anda dan buat untuk ComposerServiceProvider.php dengan konten

Samuel Kwame Antwi
sumber
1

Di dalam folder config Anda, Anda dapat membuat nama file php misalnya "variable.php" dengan konten di bawah ini:

<?php

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

Sekarang di dalam semua tampilan Anda bisa menggunakannya seperti

config('variable.versionNumber')
Mehran
sumber
Saya melakukannya dengan cara ini dalam beberapa kasus, karena informasinya benar-benar global dan Anda dapat mengaksesnya dari mana saja. Oleh karena itu, saya memanggil file konfigurasi "global.php" dan saya meletakkan apa pun di sana yang saya ingin dapat diakses di semua bagian lain dari kode saya. Satu-satunya batasan adalah ini untuk data statis, dan akan di-cache. Seharusnya tidak digunakan dengan cara ini jika Anda terus-menerus mengubah data.
eResourcesInc
1

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

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

2) dalam Model Pengguna Anda

  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) dalam Pandangan Anda

 {{ $var_messages }}
Abdelhakim Ezzahraoui
sumber
0

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

Contoh, dengan berbagi koleksi model ke semua tampilan (AppServiceProvider.php):

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

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

}
Alexander Kim
sumber
2
Ini akan menyebabkan masalah jika Anda mencoba membuat aplikasi baru dengan database kosong.
Chris Herbert
0

Anda memiliki dua pilihan:

1. Bagikan melalui fungsi Boot di App \ Providers \ AppServiceProvider

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

Dan akses variabel $ key di file tampilan mana pun.

Catatan: Ingatlah bahwa Anda tidak dapat mengakses data Sesi, Auth, Rute saat ini di sini. Opsi ini bagus hanya jika Anda ingin berbagi data statis. Misalkan Anda ingin membagikan beberapa data berdasarkan pengguna saat ini, rute, atau variabel sesi khusus apa pun yang tidak dapat Anda lakukan dengan ini.

  1. Penggunaan kelas helper Buat kelas helper di mana saja dalam aplikasi Anda dan daftarkan dalam array Alias ​​di file app.php di folder config.

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

dan buat Helper.php di folder HelperClass di dalam folder App

namespace App\HelperClass;

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

dan mengaksesnya di mana saja Helper::Sample()

Anda tidak akan dibatasi di sini untuk menggunakan Auth, Route, Session atau kelas lainnya.

Priya Chetwani
sumber