Я только начал изучать Zend Framework 2. Одна вещь, которую я не могу понять, это то, как изменить поведение платформы, когда она решает, какой шаблон представления использовать, когда я не передаю его в viewmodel.
При поиске ответа я обнаружил следующее, в котором говорится, что Zend разрешает шаблоны представления, используя приведенный ниже путь:
{normalized-module-name}/{normalized-controller-name}/{normalized-action-name}
Теперь я хочу отредактировать или удалить сегмент имени нормализованного модуля. Все файлы просмотра остаются в моей папке module / views. Причина, по которой я хочу это изменить, заключается в том, что я использую подпространства имен в качестве имени моего модуля, в результате чего первый сегмент пространства имен используется в качестве нормализованного имени модуля (что для меня недостаточно конкретно).
Чтобы дать вам пример, модуль Foo\Bar
приведет к тому, что пример будет отображен из:
/modules/Foo/Bar/view/foo/test/index.phtml
,
Я хотел бы изменить это поведение по умолчанию:
/modules/Foo/Bar/view/bar/test/index.phtml
У меня была похожая проблема, и вот мое решение.
Инжектор шаблонов по умолчанию присоединен к менеджеру событий текущего контроллера с приоритетом -90 и разрешает имя шаблона только в том случае, если модель представления не снабжена им.
Зная это, вы можете создать свой собственный шаблонный инжектор с необходимой логикой и прикрепить его к менеджеру событий с более высоким приоритетом.
Пожалуйста, смотрите код ниже:
public function onBootstrap(EventInterface $event)
{
$eventManager = $event->getApplication()->getEventManager();
$eventManager->getSharedManager()
->attach(
'Zend\Stdlib\DispatchableInterface',
MvcEvent::EVENT_DISPATCH,
new TemplateInjector(),
-80 // you can put here any negative number higher -90
);
}
Ваш шаблонный инжектор, который разрешает пути шаблона вместо пути по умолчанию.
class TemplateInjector
{
public function __invoke(MvcEvent $event)
{
$model = $event->getResult();
if (!$model instanceof ViewModel)
{
return;
}
$controller = $event->getTarget();if ($model->getTemplate())
{
return ;
}
if (!is_object($controller))
{
return;
}
$namespace = explode('\\', ltrim(get_class($controller), '\\'));
$controllerClass = array_pop($namespace);
array_pop($namespace); //taking out the folder with controllers
array_shift($namespace); //taking out the company namespace
$moduleName = implode('/', $namespace);
$controller = substr($controllerClass, 0, strlen($controllerClass) - strlen('Controller'));
$action = $event->getRouteMatch()->getParam('action');
$model->setTemplate(strtolower($moduleName.'/'.$controller.'/'.$action));
}
}
Вот ссылка из моего блога, где я написал об этом более подробно: http://blog.igorvorobiov.com/2014/10/18/creating-a-custom-template-injector-to-deal-with-sub-namespaces-in-zend-framework-2/
Начиная с zf 2.3 вы можете использовать дополнительный параметр конфигурации view_manager['controller_map']
чтобы разрешить другое разрешение имени шаблона.
Посмотрите на этот PR для получения дополнительной информации: https://github.com/zendframework/zf2/pull/5670
'view_manager' => array(
'controller_map' => array(
'Foo\Bar' => true,
),
);
В результате контроллер FQCN, начинающийся с ‘Foo \ Bar’, будет разрешен в соответствии с этими правилами:
Например: Foo\Bar\Controller\Baz\TestController
-> foo/bar/baz/test/actionname
Обновить:
Начиная с Zend-MVC v3.0, это поведение по умолчанию
Правильный шаблон для ViewModel внедряется в событие MVC ‘dispatch’ (определено в ViewManager) от Zend\Mvc\View\Http\InjectTemplateListener
с приоритетом -90
Вам нужно будет создать собственный InjectTemplateListener и зарегистрировать его с более высоким приоритетом для того же события.
Но я бы рекомендовал устанавливать шаблон в каждом действии вручную из-за производительности — смотрите http://samminds.com/2012/11/zf2-performance-quicktipp-1-viewmodels/
Определение имени шаблона — это сложный процесс (для системных ресурсов), и во всех статьях о производительности ZF2 говорится, что вы должны предоставить имя шаблона вручную, чтобы повысить производительность.
так что не тратьте время на поиск способа сделать то, что вы в конечном итоге будете делать вручную: D
Чтобы улучшить ответ Next Developer, я пишу следующий код в TemplateInjector.php:
class TemplateInjector
{
public function __invoke(MvcEvent $event)
{
$model = $event->getResult();
if (!$model instanceof ViewModel) {
return;
}
if ($model->getTemplate()) {
return;
}
$controller = $event->getTarget();
if (!is_object($controller)) {
return;
}
$splitNamespace = preg_split('/[\\\]+/', ltrim(get_class($controller), '\\'));
$moduleName = $splitNamespace[1];
$controller = $splitNamespace[0];
$action = $event->getRouteMatch()->getParam('action');
$model->setTemplate(strtolower($moduleName . '/' . $controller . '/' . $action));
}
}
Я изменил способ построения шаблона. Использование регулярных выражений быстрее, чем использование методов массива.