Home » Php » php – View composer runs multiple times, how to reduce to 1

php – View composer runs multiple times, how to reduce to 1

Posted by: admin July 12, 2020 Leave a comment

Questions:

I made a view composer in Laravel 5. When i use a wildcard *, to add something to all my views, it get’s called at least twice. It runs when my master template is loaded, and again when my content page is included. This will give problems in the future, because it executes the query it does multiple times. I was able to fix the multiple querying by storing it in a static variable :

class StoreComposer {


static $composed;


public function __construct(StoreRepository $repository)
{
    $this->store = $repository;
}


public function compose(View $view)
{

    if(static::$composed)
    {
        return $view->with('store', static::$composed);
    }


    static::$composed = $this->store->pushCriteria( new WithCategories() )
        ->pushCriteria( new WithSettings() )
        ->applyCriteria()
        ->all();

    $view->with('store', static::$composed);
}

} 

My question is, is there a way to make sure it only runs once, no matter how many views i load, or is there another solution to this? The way i fixed it now doesn’t feel right to me. Thanks!

How to&Answers:

Unfortunately no, there is no way to make it run once, due to the way View Composers are implemented. The Illuminate\View\View::renderContents() method is responsible for calling the composer bound to a view, and since any form of view rendering (Blade template inheritance or simple @include statements) executes that method, it means that when any view is rendered any composer bound to it gets triggered.

Since in your case you use a * wildcard to bind all views, if your page renders ten views, the composer will get executed ten times. However your approach looks like a good solution to solve this shortcoming.

Answer:

Try this singleton solution or use cache https://laracasts.com/discuss/channels/laravel/executing-a-view-composer-only-once

On Laravel 5.6.38 works fine