Как передать данные во все представления в Laravel 5?


125

Я хочу, чтобы некоторые данные по умолчанию были доступны во всех представлениях моего приложения Laravel 5.

Я пытался найти его , но только найти результаты для Laravel 4. Я прочитал документацию «Обмен данными со всеми Просмотров : » здесь , но я не могу понять , что делать. Где следует разместить следующий код?

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

Спасибо за вашу помощь.


ну, вам нужен код запуска для выполнения этого требования?
Safoor Safdar,

1
Heads Up, используя View :: share в поставщике услуг с результатами вызова базы данных, приведет к ошибке приложения при выполнении миграции обновления базы данных или попытке запустить сумрак с недоступным подключением к базе данных (длинная история, .env.dusk.local - это используется только после запуска поставщика услуг). Как указано ниже, лучше всего подходит базовый контроллер или промежуточное программное обеспечение.
Энди Лобель

Также будьте осторожны при использовании *составителей представлений, особенно при использовании запросов к базе данных, поскольку они запускаются для каждого включенного подвида, компонента и т. Д., Поэтому вы можете запустить сотни ненужных запросов, лучше всего использовать базовое представление, например макеты. приложение затем передает данные по мере необходимости.
Энди Лобель

Ответы:


222

Этой цели можно достичь разными способами,

1. Использование BaseController

Как мне нравится, я создаю BaseControllerкласс, расширяющий собственный Laravel Controller, и настраиваю там различные глобальные вещи. Все остальные контроллеры затем расширяются, BaseControllerа не из контроллера 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. Использование фильтра

Если вы точно знаете, что хотите, чтобы что-то было настроено для представлений по каждому запросу во всем приложении, вы также можете сделать это с помощью фильтра, который запускается перед запросом - именно так я работаю с объектом User в Laravel.

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

ИЛИ

Вы можете определить свой собственный фильтр

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

и вызвать его через простой вызов фильтра.

Обновление согласно версии 5. *

3. Использование промежуточного программного обеспечения

Используя View::shareсmiddleware

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



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

4. Использование View Composer

View Composer также помогает привязать определенные данные для просмотра разными способами. Вы можете напрямую привязать переменную к определенному представлению или ко всем представлениям. Например, вы можете создать свой собственный каталог для хранения файла композитора представления в соответствии с требованиями. и эти файлы композитора представления через Службу обеспечивают взаимодействие с представлением.

Метод View composer может использоваться по-разному. Первый пример может выглядеть одинаково:

Вы можете создать App\Http\ViewComposersкаталог.

Поставщик услуг

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

После этого добавьте этого провайдера в config / app.php в разделе «провайдеры».

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

Этот метод может помочь только для определенного вида. Но если вы хотите запускать ViewComposer для всех представлений, мы должны применить это единственное изменение к ServiceProvider.

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

Ссылка

Документация Laravel

Для дальнейшего разъяснения Эпизод Laracast

Если с моей стороны все еще что-то неясно, дайте мне знать.


В вашем примере отсутствует register()метод - он не является обязательным
Джонатан

@jonathan, спасибо, что указал на это, но пример содержит только те разделы, о которых нужно позаботиться. перспектива обмена данными с представлением.
Safoor Safdar

где вы ставите фильтр? вероятно, наиболее правильный ответ сейчас - использование групп промежуточного программного обеспечения laravel.com/docs/5.3/middleware#middleware-groups или глобального промежуточного программного обеспечения
Toskan

7
Это не очень хорошая идея. Компоновщики представлений создают экземпляр композитора для каждого отдельного представления. Это означает, что если вы запустите цикл в 1000 раз, будет создано 1000 экземпляров композитора и 1000 раз будет обработано событие запуска, чего вы не хотите.
Реза Шадман

4
@RezaShadman прав! Я усвоил это на собственном горьком опыте. Мое приложение работало так медленно, пока я не установил инструмент laravel-debugbar для исследования. Затем я понял, что все 8 запросов выполнялись примерно 15 раз для загрузки одной страницы. Это потому, что композитор представления будет вызываться для каждого включаемого файла лезвия. Это если вы используете звездочку *. Если вы не используете, *то все будет в порядке.
Syclone

66

Вы можете создать своего собственного поставщика услуг ( ViewServiceProviderимя общепринятое) или использовать существующего AppServiceProvider.

В выбранном вами провайдере поместите свой код в метод загрузки.

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

Это сделает $dataпеременную доступной во всех ваших представлениях.

Если вы предпочитаете использовать фасад вместо помощника, измените его view()->на, View::но не забудьте, чтобы он был use View;в верхней части файла.


Спасибо, отлично работает. Предназначена ли функция загрузки для такого рода вещей, или вы рекомендуете создать моего собственного поставщика услуг?
Рагнарссон

2
Если у вас есть только одна или две вещи, AppServiceProviderкоторыми вы можете поделиться, это нормально, но если у вас есть что-то большее, вам следует подумать о создании нового провайдера.
Marwelln

Он работал, но я просто вижу, что сегодня он не работает! использование composer updateтоже не работает. На самом деле это вообще не стреляет boot(). Мне нужно поделиться двумя переменными.
itsazzad 01

11
Имейте в виду, что это не сработает, если вы извлекаете записи из базы данных, так как это будет вызвано перед выполнением миграции. Таким образом, вы в основном пытаетесь получить записи из базы данных до того, как они появятся. По крайней мере, мне кажется, что так оно и есть.
lorey

1
К сожалению, похоже, что это не работает с совместным использованием авторизованного пользователя Auth :: user (), ответ Сафура №1, ниже этого, работает :)
Стэн Смолдерс,

11

Я обнаружил, что это самый простой способ. Создайте нового поставщика и используйте '*'подстановочный знак, чтобы прикрепить его ко всем представлениям. Работает и в 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()
    {
        //
    }
}

2
Добавьте этого провайдера в массив провайдеров в вашем config / app «App \ Providers \ ViewServiceProvider :: class»,
Nadeem0035,

8

Лучшим способом было бы поделиться переменной с помощью View::share('var', $value);

Проблемы с составлением при использовании "*":

Рассмотрим следующий подход:

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

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

Из примера вида лезвия:

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

Что случается?

  • GlobalComposerКласс инстанциируется 1000 раз используя App::make.
  • Событие composing:some_partial_view_to_display_iобрабатывается 1000 раз.
  • composeФункция внутри GlobalComposerкласса называется 1000 раз.

Но частичный вид не some_partial_view_to_display_iимеет ничего общего с составленными переменными, GlobalComposerа сильно увеличивает время рендеринга.

Лучший подход?

Использование View::shareсгруппированного промежуточного программного обеспечения.

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

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

});

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

Обновить

Если вы используете что-то, что вычисляется по конвейеру промежуточного программного обеспечения, вы можете просто прослушать соответствующее событие или поместить промежуточное программное обеспечение общего доступа к просмотру в последний конец конвейера.


4

В документации:

Как правило, вы должны размещать вызовы метода share в методе загрузки поставщика услуг. Вы можете добавить их в AppServiceProvider или создать отдельного поставщика услуг для их размещения.

Я согласен с Marwelln, просто вставьте его AppServiceProviderв функцию загрузки:

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

Я рекомендую использовать конкретное имя для переменной, чтобы избежать путаницы или ошибок с другими, не «глобальными» переменными.


3

Документация слышна https://laravel.com/docs/5.4/views#view-composers, но я сломаю ее

  1. Найдите каталог app \ Providers в корневом каталоге вашего приложения и создайте файл ComposerServiceProvider.php, скопируйте и вставьте в него текст ниже и сохраните его.

    <?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. В корне вашего приложения откройте Config / app.php и найдите в файле раздел Providers, скопируйте и вставьте этот App \ Providers \ ComposerServiceProvider в массив.

Сделав это, мы создали поставщика услуг Composer. Когда вы запускаете свое приложение с представлением Profile, например http: // yourdomain / something / profile , вызывается поставщик услуг ComposerServiceProvider, и создается экземпляр класса App \ Http \ ViewComposers \ ProfileComposer, вызывающего метод Composer из-за кода ниже внутри метод или функция загрузки.

 // Using class based composers...
 View::composer(
   'profile', 'App\Http\ViewComposers\ProfileComposer'
 );
  1. Если вы обновите свое приложение, вы получите сообщение об ошибке, потому что класс App \ Http \ ViewComposers \ ProfileComposer еще не существует. Теперь давайте создадим его.

Перейдите в путь к каталогу app / Http

  • Создайте каталог под названием ViewComposers

  • Создайте файл 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());
        }
    }

Теперь перейдите к вашему представлению или, в данном случае, Profile.blade.php и добавьте

{{ $count }}

и это покажет количество пользователей на странице профиля.

Чтобы показать счетчик на всех страницах, измените

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

к

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

<? php и пространство имен App \ Http \ ViewComposers; используйте Illuminate \ Contracts \ View \ View; отсутствует в
ProfileComposer.php



1

Внутри папки конфигурации вы можете создать файл php, назовите его, например, «variable.php», с содержимым ниже:

<?php

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

Теперь внутри всех представлений вы можете использовать это как

config('variable.versionNumber')

Я делаю это в некоторых случаях, потому что информация действительно глобальна, и вы можете получить к ней доступ откуда угодно. По этой причине я называю файл конфигурации global.php и помещаю туда все, что я хочу, чтобы было доступно во всех других частях моего кода. Единственное ограничение - это статические данные, которые кэшируются. Его не следует использовать таким образом, если у вас постоянно меняются данные.
eResourcesInc

1

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

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

2) в вашей модели пользователя

  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) на ваш взгляд

 {{ $var_messages }}

0

Метод Laravel 5.6: https://laravel.com/docs/5.6/views#passing-data-to-views

Пример с совместным использованием коллекции моделей для всех представлений (AppServiceProvider.php):

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

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

}

2
Это вызовет проблемы, если вы попытаетесь создать новое приложение с пустой базой данных.
Крис Герберт

0

У вас есть два варианта:

1. Поделиться через функцию загрузки в App \ Providers \ AppServiceProvider

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

И получить доступ к переменной $ key в любом файле представления.

Примечание. Помните, что здесь вы не можете получить доступ к данным текущего сеанса, аутентификации и маршрута. Этот вариант хорош, только если вы хотите поделиться статическими данными. Предположим, вы хотите поделиться некоторыми данными на основе текущего пользователя, маршрута или любой настраиваемой переменной сеанса, которую вы не сможете сделать с этим.

  1. Использование вспомогательного класса. Создайте вспомогательный класс в любом месте вашего приложения и зарегистрируйте его в массиве Alias ​​в файле app.php в папке config.

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

и создайте Helper.php в папке HelperClass в папке приложения

namespace App\HelperClass;

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

и получить доступ к нему где угодно, как Helper::Sample()

Здесь вы не будете ограничены использованием Auth, Route, Session или любых других классов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.