Laravel ViewServiceProvide does not takes multiple views

Viewed 847

My Laravel version is 5.8.23

According to the documentation on Laravel View Composer, in order to attach a view composer to multiple views at once, pass the views in an array inside the first argument like:

View::composer(['profile', 'dashboard'],
    'App\Http\View\Composers\MyViewComposer');

When I try to use similar like that, my second value in the array does not get the values I passed in the AnimalComposer.php

My code:

View::composer(['animal.edit', ' animal.create'],
            'App\Http\Views\Composers\AnimalComposer'
        );

I get errorException in animal/create.blade.php

Undefined variable: animalType

But if I use multiple View::composer to send the data to the blade.php, it is working fine.

public function boot()
{
    View::composer('animal.edit',
        'App\Http\Views\Composers\AnimalComposer'
    );
    View::composer('animal.create',
        'App\Http\Views\Composers\AnimalComposer'
    );
}

EDIT My AnimalComposer.php file

//AnimalComposer.php

namespace App\Http\Views\Composers;
use App\AnimalType;
use App\Helpers\GenderHelper;

class AnimalComposer
{
    public function compose($view)
    {
        $animalType = AnimalType::pluck('name', 'id');
        $genderLists = GenderHelper::getGenderSelectArray();

        $view->with('animalType', $animalType)
            ->with('genderLists', $genderLists);
    }

}

Am I missing something? Do I need to use View::composer every time I send AnimalComposer to the view? Does Laravel now do not support multiple views inside array?

2 Answers

Follow these steps,

  1. Create view composer service provider.
php artisan make:provider ViewComposerServiceProvider
  1. Add provider to confing/app.php
  'providers' => [
     ...
        App\Providers\ViewComposerServiceProvider::class,
     ...
  ];

3.In your ViewComposerServiceProvider, I have created composeHeader, and composeFooter methods for demo, you can create your own methods in this way.

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->composeHeader();
        $this->composeFooter();
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    private function composeHeader()
    {
        view()->composer('front.layouts.partials.header', 'App\Http\ViewComposers\HeaderComposer@compose');
    }

    private function composeFooter()
    {
        view()->composer('front.layouts.partials.footer', 'App\Http\ViewComposers\FooterComposer@compose');
    }
  1. in App\Http\ViewComposers\FooterComposer and App\Http\ViewComposers\HeaderComposer, you can share objects or collection in this way
use App\Models\Admin\Menu;
class HeaderComposer
{
    /**
     * Create a new profile composer.
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function compose(View $view)
    {
        $menuitems = Menu::where('parent_id',0)->where('status',1)->get();
        $view->with('menuitems', $menuitems);
    }
}
  1. composer dump-autoload

  2. Now you can access $menuitems collection in front.layouts.partials.header partials anywhere.

Thats all

After having a look at the Laravel illuminate source code, there is also a method called composers where the key becomes the callback:

View::composers(
    [
        'App\Http\Views\Composers\AnimalComposer' => ['animal.edit', ' animal.create']
    ]);

As seen in vendor/laravel/framework/src/Illuminate/View/Concerns/ManagesEvents@composers. It's not mentioned in the documentation.

@Bimal Prasad Pandey's proposition is solid. If you work on a big project, Bimal's idea is preferable.

Related