kokoshneta's avatar

Change order of view composers

Is there a way to specify in what order view composers are called?

From testing, it looks like the general order is that wildcard composers are executed last, which seems like exactly the opposite of what it should be. To give an example of what I mean, consider this:

// ViewServiceProvider.php
public function boot() {
	View::composer('*', function($view) {
		$view->with([
			'shared_thingy' => 100,
			'thingy_two' => 50
		]);
	}

	View::composer('specific-route', function($view) {
		$view->with([
			'shared_thingy' => 500
		]);
	}
}

If you load /specific-route and output $shared_thingy, it will output 100 rather than 500, and outputting $thingy_two will output 50. This may be desirable in some cases, but in other cases, it’s very undesirable.

I have one variable in particular which I share and use with all views, except I don’t want to share it with Livewire components, because it interferes with the business logic there. I have a view composer for livewire/*, and I would thus like to exclude this value from that. This would be easy to do if the wildcard composer was run first, so that other composers could override it – but I can’t think of a way to do it when the wildcard composer comes last.

So is there a way to

  • make sure wildcard composers are always run first; or
  • somehow prevent the wildcard composer from sharing certain things based on something defined in a previously executed composer?

I know that I can do if (Route::currentRouteName() != 'xyz') $view->share(...) in the wildcard composer, but as the number of ‘exceptions’ to wildcard sharing grows, that can quickly become very unwieldy. It would be more efficient to define in the specific composers which things to skip.

0 likes
4 replies
kokoshneta's avatar

@tykus That is so clever and so obvious I can’t believe I’ve just spent three hours going back and forth between various workarounds without it even crossing my mind once. Off to test!

Snapey's avatar

@kokoshneta Be very careful with wildcards since they can be executed for every view, including partials and components.

kokoshneta's avatar

@tykus It only bloody worked – excellent!

@snapey Yeah, that is what I want in this particular case (except for Livewire components). Translation is on this site is driven by strings fetched from a database table rather than translation files, and since every single view, partial and component contains at least one element of text that needs to be properly translated when switching languages, I universally share a (singleton) object containing all the necessary strings in the active language, so it’s available as a simple variable wherever I am. More or less everything else gets shared on a per-view basis.

Please or to participate in this conversation.