Laravel:从模块扩展视图



我的Laravel应用程序中有一个模块(它也可能是一个composer包)。该模块有一个视图编辑器,它为所有视图设置一个数组,其中包含应用程序主导航中应包含的路线。

作曲家是这样的:


class ContactNavigationComposer
{
/**
* Bind data to the view.
*
* @param  IlluminateViewView  $view
* @return void
*/
public function compose(View $view)
{
$view->with('contactNavigation', config('contact.navigation'));
}
}

然后在应用程序的mainNav中,该变量$contactNavigation被迭代以生成条目:

<ul>
# ...
<li>
<a 
class="{{ (request()->is('navigations/areas')) ? 'active' : '' }}" 
href="{{ route('areas.index') }}">
Navigation Areas
</a>
</li>
<li>
<a 
class="{{ (request()->is('languages')) ? 'active' : '' }}" 
href="{{ route('languages.index') }}">
Languages
</a>
</li>
@foreach($contactNavigation as $text => $url)
<li>
<a 
class="{{ (request()->is($url)) ? 'active' : '' }}" 
href="{{ $url }}">
{{ $text }}
</a>
</li>
@endforeach
</ul>

这非常好,但我想知道我是否可以以更动态的方式进行这种行为,并让不同模块的作曲家使用相同的数组,例如$modules,它包含不同模块的导航条目(和其他内容)。这样以后我就不必在应用程序视图中添加模块扩展了。所以我建议的解决方案是smth。像这样:

class ContactNavigationComposer
{
/**
* Bind data to the view.
*
* @param  IlluminateViewView  $view
* @return void
*/
public function compose(View $view)
{
$view->with('modules.navigation.contact', config('contact.navigation'));
}
}
<ul>
# ...
@if (isset($modules['navigation']))
@foreach($modules['navigation'] as $moduleNavigation)
@foreach($moduleNavigation as $text => $url)
<li>
<a 
class="{{ (request()->is($url)) ? 'active' : '' }}" 
href="{{ $url }}">
{{ $text }}
</a>
</li>
@endforeach
@endforeach
@endif
</ul>

当然,对于点表示法,这个modules.navigation.contact键永远不会被转换成视图变量,尤其是数组。

有什么方法可以实现这样的目标吗?

对于那些也遇到这个问题的人:我把我的构图方法改成了这个

// ViewComposer
class ContactNavigationComposer extends BaseComposer
{
public function compose(View $view)
{
$moduleDataBag = $this->getModuleDataBag($view);
$moduleData = $moduleDataBag->mergeRecursive([
'contact' => [
'navigation' => config('contact.navigation.entries')
]
]);
$view->with('modules', $moduleData);
}
}

getModuleDataBag-方法来自每个ViewComposer从中继承的BaseComposer-类。

class BaseComposer
{
protected function getModuleDataBag(View $view)
{
if (!array_key_exists(config('contact.view.dataKey'), $view->gatherData())) {
ViewFacade::share(config('contact.view.dataKey'), collect([]));
}
return $view->gatherData()[config('contact.view.dataKey')];
}
}

存储所有配置的密钥在(可发布的)配置中定义。通过这种方式,这种设置对于周围应用程序的修改是灵活的。(这个包被称为contact,这就是为什么视图数据键在contact配置中的原因。)如果找不到所需的键,BaseComposer会使用View facade上的::share-方法将其设置为所有视图,作为一个空集合。

每个ViewComposer总是首先调用getModuleDataBag-方法来接收可能已经由其他ViewComposer设置的当前数据。

由于此$moduleDataBag是一个集合,所以只要是数组,所有附加值都可以合并到其中。这是递归完成的,以便保留每个现有的键和值。

希望以后能帮助到别人。

最新更新