Laravel:从模块扩展视图

问题描述

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

作曲家看起来像这样:


class ContactNavigationComposer
{
    /**
     * Bind data to the view.
     *
     * @param  \Illuminate\View\View  $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  \Illuminate\View\View  $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-key 永远不会被转换成视图变量,尤其是作为一个数组。

有没有办法实现这样的目标?

解决方法

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

// 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-config 中的原因。) 如果未找到预期的键,则 BaseComposer 将其设置为使用视图外观上的 ::share 方法作为空集合的所有视图。

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

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

希望以后能帮到人。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...