Como passar dados para todas as visualizações no Laravel 5?

125

Quero ter alguns dados padrão acessíveis em todas as visualizações no meu aplicativo Laravel 5.

Tentei procurá-lo, mas só encontrei resultados para o Laravel 4. Li a documentação 'Compartilhando dados com todas as visualizações' aqui, mas não consigo entender o que fazer. Onde o código a seguir deve ser colocado?

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

Obrigado pela ajuda.

Ragnarsson
fonte
bem, você precisa de um código de inicialização para gerenciar esse requisito?
Safoor Safdar
1
heads-up usando View :: share em um provedor de serviços com os resultados de uma chamada ao banco de dados irá errar o aplicativo ao executar uma migração de atualização do db ou ao tentar executar o crepúsculo com uma conexão db inacessível (história longa, .env.dusk.local é usado somente após a execução do provedor de serviços). Como mencionado abaixo em um controlador de base ou middlware, é o melhor.
Andy Lobel
Também tenha cuidado ao usar *compositores no modo de exibição, especialmente se estiver usando consultas db, pois ele é executado para todas as sub-visualizações, componentes etc., para que você possa executar centenas de consultas desnecessárias, o melhor é usar a exibição base, por exemplo, layouts. O aplicativo passa os dados conforme necessário.
Andy Lobel

Respostas:

221

Esse objetivo pode ser alcançado através de diferentes métodos,

1. Usando o BaseController

Do jeito que eu gosto de organizar as coisas, faço uma BaseControlleraula que se estende ao próprio Laravel Controllere montei várias coisas globais por lá. Todos os outros controladores se estendem BaseControllerdo Controlador do 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. Usando filtro

Se você sabe que deseja configurar algo para exibições em todas as solicitações em todo o aplicativo, também pode fazê-lo através de um filtro que é executado antes da solicitação - é assim que trato do objeto Usuário no Laravel.

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

OU

Você pode definir seu próprio filtro

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

e chame-o através de uma simples chamada de filtro.

Atualização de acordo com a versão 5. *

3. Usando Middleware

Usando o View::sharecommiddleware

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



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

4. Usando o View Composer

O View Composer também ajuda a vincular dados específicos para exibição de maneiras diferentes. Você pode vincular diretamente a variável a uma visualização específica ou a todas as visualizações. Por exemplo, você pode criar seu próprio diretório para armazenar seu arquivo do compositor de exibição de acordo com o requisito. e esses arquivos do compositor de visualizações através do Serviço fornecem interação com a visualização.

View compositor método pode usar de maneira diferente, primeiro exemplo pode ser parecido:

Você pode criar um App\Http\ViewComposersdiretório.

Provedor de serviço

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

Depois disso, adicione esse provedor ao config / app.php na seção "fornecedores".

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 pode ajudar apenas para a visualização específica. Mas se você deseja acionar o ViewComposer em todos os modos de exibição, precisamos aplicar essa única alteração ao ServiceProvider.

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

Referência

Documentação do Laravel

Para maiores esclarecimentos, o episódio Laracast

Se ainda houver algo claro do meu lado, me avise.

Safoor Safdar
fonte
Seu exemplo está faltando o register()método - não é opcional
Jonathan
@ Jonathan obrigado a destacar, mas o exemplo contém apenas as seções que precisam ser cuidadas. perspectiva de compartilhar dados com o view.
Safoor Safdar
onde você coloca o filtro? provavelmente a resposta mais correta agora está usando grupos de middleware laravel.com/docs/5.3/middleware#middleware-groups ou middleware mundial
Toskan
7
Isso não é uma boa ideia, os compositores de exibição criam a instância do compositor para cada exibição individual, ou seja, se você executar um loop de 1000 vezes, serão criadas 1000 instâncias do compositor e, 1000 vezes, o evento de disparo será tratado, o que não é o que você deseja.
Reza Shadman
4
@RezaShadman está correto! Eu aprendi isso da maneira mais difícil. Meu aplicativo estava executando tão lento até instalar a ferramenta laravel-debugbar para investigar. Então percebi que todas as 8 consultas eram executadas cerca de 15 vezes para um único carregamento de página. Isso ocorre porque o compositor de exibição será chamado para cada arquivo blade incluído. Ou seja, se você estiver usando o asterisco *. Se você não estiver usando o, *então você deve estar bem.
Syclone 23/05
66

Você pode criar seu próprio provedor de serviços (o ViewServiceProvidernome é comum) ou pode usar o existente AppServiceProvider.

No provedor selecionado, coloque seu código no método de inicialização.

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

Isso tornará uma $datavariável acessível em todas as suas visualizações.

Se você preferir usar a fachada em vez do auxiliar, mude view()->para, View::mas não esqueça de ter use View;na parte superior do arquivo.

Marwelln
fonte
Obrigado, trabalhando muito bem. A função de inicialização é destinada a esse tipo de coisa ou você recomenda criar meu próprio provedor de serviços?
Ragnarsson
2
Se você tiver apenas uma ou duas coisas para compartilhar, não AppServiceProviderhá problema, mas se tiver algo mais do que isso, considere criar um novo provedor.
Marwelln
Estava funcionando, mas vejo que não está funcionando hoje! usando composer updatetambém não está funcionando. Na verdade, não está disparando boot()nada. Eu preciso compartilhar duas variáveis.
itsazzad
11
Esteja ciente de que isso não funcionará se você estiver buscando registros do banco de dados, pois isso será chamado antes de executar migrações. Então, você está basicamente tentando buscar registros do banco de dados antes que eles existam. Pelo menos esse parece ser o meu caso.
Lorey # 4/15
1
Infelizmente, isso não parece trabalhar com a partilha de um usuário conectado Auth :: utilizador (), a resposta # 1 de Safoor, abaixo deste, faz :)
Stan Smulders
11

Eu achei que era o mais fácil. Crie um novo provedor e use o '*'curinga para anexá-lo a todas as visualizações. Também funciona em 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
fonte
2
Adicione este provedor ao conjunto de provedores no seu config / app "App \ Providers \ ViewServiceProvider :: class"
Nadeem0035 7/16/16
8

A melhor maneira seria compartilhar a variável usando View::share('var', $value);

Problemas com a composição usando "*":

Considere a seguinte abordagem:

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

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

De uma visualização de lâmina de exemplo:

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

O que acontece?

  • A GlobalComposerclasse é instanciada 1000 vezes usando App::make.
  • O evento composing:some_partial_view_to_display_ié tratado 1000 vezes.
  • A composefunção dentro da GlobalComposerclasse é chamada 1000 vezes.

Mas a visão parcial some_partial_view_to_display_inão tem nada a ver com as variáveis ​​compostas, GlobalComposermas aumenta bastante o tempo de renderização.

Melhor abordagem?

Usando View::sharejunto um 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());
  }
}

Atualizar

Se você estiver usando algo calculado no pipeline de middleware, poderá simplesmente ouvir o evento apropriado ou colocar o middleware de compartilhamento de exibição na última parte inferior do pipeline.

Reza Shadman
fonte
4

Na documentação:

Normalmente, você faria chamadas para o método de compartilhamento no método de inicialização de um provedor de serviços. Você pode adicioná-los ao AppServiceProvider ou gerar um provedor de serviços separado para alojá-los.

Estou de acordo com Marwelln, basta colocá-lo na AppServiceProviderfunção de inicialização:

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

Eu recomendo usar um nome específico para a variável, para evitar confusões ou erros com outras variáveis ​​não globais.

Santiago Mendoza Ramirez
fonte
3

A documentação é ouvida https://laravel.com/docs/5.4/views#view-composers, mas eu irei dividir

  1. Procure o diretório app \ Providers no diretório raiz do seu aplicativo e crie o arquivo ComposerServiceProvider.php, copie e cole o texto abaixo nele e salve-o.

    <?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. Na raiz do seu aplicativo, abra Config / app.php e procure a seção Providers no arquivo, copie e cole este 'App \ Providers \ ComposerServiceProvider', na matriz.

Ao fazer isso, criamos o Composer Service Provider. Quando você executa o aplicativo com o perfil Visualizar como http: // seudominio / algo / perfil , o provedor de serviços ComposerServiceProvider é chamado e a classe App \ Http \ ViewComposers \ ProfileComposer é instanciada chamando o método Composer devido ao código abaixo dentro do método ou função de inicialização.

 // Using class based composers...
 View::composer(
   'profile', 'App\Http\ViewComposers\ProfileComposer'
 );
  1. Se você atualizar o aplicativo, receberá um erro porque a classe App \ Http \ ViewComposers \ ProfileComposer ainda não existe. Agora vamos criá-lo.

Vá para o caminho do diretório app / Http

  • Crie o diretório chamado ViewComposers

  • Crie o arquivo 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());
        }
    }

Agora vá para a sua visão ou, neste caso, Profile.blade.php e adicione

{{ $count }}

e isso mostrará a contagem de usuários na página de perfil.

Para mostrar a contagem em todas as páginas, mude

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

Para

// Using class based composers...
View::composer(
    '*', 'App\Http\ViewComposers\ProfileComposer'
);
Samuel Kwame Antwi
fonte
<? php e espaço para nome App \ Http \ ViewComposers; use Illuminate \ Contracts \ View \ View; está faltando no ProfileComposer.php
Unicco 17/04
1

A documentação está aqui https://laravel.com/docs/5.4/views#view-composers, mas eu a detalharei 1. Procure o diretório Providers no diretório raiz e crie o ComposerServiceProvider.php com conteúdo

Samuel Kwame Antwi
fonte
1

Dentro da sua pasta de configuração, você pode criar um nome de arquivo php, por exemplo "variable.php", com o conteúdo abaixo:

<?php

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

Agora, dentro de todas as visualizações, você pode usá-lo como

config('variable.versionNumber')
Mehran
fonte
Eu faço dessa maneira em alguns casos, porque as informações são verdadeiramente globais e você pode acessá-las de qualquer lugar. Por esse motivo, chamo o arquivo de configuração "global.php" e coloco qualquer coisa que eu queira que seja acessível em todas as outras partes do meu código. A única limitação é que isso é para dados estáticos e é armazenado em cache. Não deve ser usado dessa maneira se você alterar constantemente os dados.
eResourcesInc
1

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

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

2) no seu modelo de usuário

  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) na sua opinião

 {{ $var_messages }}
Abdelhakim Ezzahraoui
fonte
0

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

Exemplo, com o compartilhamento de uma coleção de modelos para todas as visualizações (AppServiceProvider.php):

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

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

}
Alexander Kim
fonte
2
Isso causará problemas se você estiver tentando criar um aplicativo novo com um banco de dados vazio.
Chris Herbert
0

Você tem duas opções:

1.Share via função de inicialização em App \ Providers \ AppServiceProvider

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

E acesse a variável $ key em qualquer arquivo de exibição.

Nota: Lembre-se de que você não pode acessar os dados atuais da sessão, autenticação e rota aqui. Essa opção é boa apenas se você deseja compartilhar dados estáticos. Suponha que você queira compartilhar alguns dados com base no usuário atual, rota ou qualquer variável de sessão personalizada que não possa fazer com isso.

  1. Uso de uma classe auxiliar Crie uma classe auxiliar em qualquer lugar do seu aplicativo e registre-a na matriz Alias ​​no arquivo app.php na pasta config.

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

e crie Helper.php na pasta HelperClass na pasta App

namespace App\HelperClass;

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

e acessá-lo em qualquer lugar como Helper::Sample()

Você não será restrito aqui a usar Auth, Route, Session ou quaisquer outras classes.

Priya Chetwani
fonte