我找到了这个主题并回答:Change layout in the controller of Zend Framework 2.0 :: Answer
我正在尝试这样做:
public function loginAction() {
if ($this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('zfcadmin');
}
$this->layout('layout/login');
return new ViewModel();
}
但它不起作用。
当然我有档案MODULE_DIR/view/layout/login.phtml
。
我在设置布局之前尝试var_dump($this->layout());
,然后在显示之后,$this->layout('layout/login');
行之后更改了布局。但事实并非如此。
如何在控制器中设置不同的布局?
另外,如果布局发生变化,我为什么不收到任何消息? 为什么标签布局已加载,而不是错误?
我想,我必须在某处设置布局(比如我设置路线)。可能在配置['view_manager']['template_map']
中添加如下内容:
$config = array(
'view_manager' => array(
'template_path_stack' => array(
__DIR__ . '/../view'
),
'template_map' => array(
'layout/login' => __DIR__ . '/../view/layout/login.phtml',
),
),
);
- 就像说there:
当然你也需要定义那些布局......只需检查 应用程序模块
module.config.php
,以了解如何定义布局。
那对我没有帮助:(
试过这个:
public function loginAction() {
if ($this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('zfcadmin');
}
$layout = $this->layout();
$layout->setTemplate('layout/login');
return new ViewModel();
}
建议为@alex。不起作用:'(。没有return new ViewModel();
行的结果相同。
您自己查看文件:
layout/login
我按照你的建议尝试调试。
我更新了__invoke
功能:
public function __invoke($template = null)
{
var_dump($template);
die();
if (null === $template) {
return $this->getViewModel();
}
return $this->setTemplate($template);
}
有些情况:
使用代码,您建议:
$layout = $this->layout();
$layout->setTemplate('layout/login');
它显示NULL。所以调用方法,但$template
是空变量。
代码来自post,我在帖子的开头给出了:
$this->layout('layout/login');
return new ViewModel();
显示string(12) "layout/login"
。
没有任何代码(因此加载了布局layout/admin
(默认为ZfcAdmin
),它会显示:string(12) "layout/admin"
。
如果我加载了我的网站的/
,那么该网页就会加载标准布局(在两种情况下,模块配置中都有layout/layout
。
我试过了:
$layout = $this->layout();
var_dump($layout->getTemplate());
$layout->setTemplate('layout/login');
var_dump($layout->getTemplate());
die();
在控制器中。它显示:string(13) "layout/layout" string(12) "layout/login"
。所以布局改变了。但标准布局layout/layout
已呈现,而不是layout/login
。 :(
答案 0 :(得分:2)
由于您正在使用ZfcAdmin
和,因此在该模块中启用了use_admin_layout
选项和您的登录路线是'重新尝试设置布局是ZfcAdmin的子路由,管理布局监听器正在开始并覆盖您尝试在控制器操作中设置的模板。
最简单的方法是禁用zfcadmin布局,编写自己的监听器并处理登录布局的具体情况。您可以使用与ZfcAdmin在Module.php中使用的方法基本相同的方法,使用一两个调整...
请务必禁用ZfcAdmin布局
'zfcadmin' => array(
'use_admin_layout' => false,
),
然后,使用您的模块名称作为配置密钥,设置您自己的相同配置版本...
'myzfcadmin' => array(
'use_admin_layout' => true,
'admin_layout_template' => 'layout/admin',
// you could even define a login layout template here
'login_layout_template' => 'layout/login',
),
接下来在MyZfcAdmin/Module.php
添加一个监听器,几乎与ZfcAdmin中的监听器一样,只检查你的myzfcadmin
配置值...
public function onBootstrap(MvcEvent $e)
{
$app = $e->getParam('application');
$em = $app->getEventManager();
$em->attach(MvcEvent::EVENT_DISPATCH, array($this, 'selectLayoutBasedOnRoute'));
}
public function selectLayoutBasedOnRoute(MvcEvent $e)
{
$app = $e->getParam('application');
$sm = $app->getServiceManager();
$config = $sm->get('config');
if (false === $config['myzfcadmin']['use_admin_layout']) {
return;
}
$match = $e->getRouteMatch();
$controller = $e->getTarget();
if (!$match instanceof \Zend\Mvc\Router\RouteMatch
|| 0 !== strpos($match->getMatchedRouteName(), 'zfcadmin')
|| $controller->getEvent()->getResult()->terminate()
) {
return;
}
if ($controller instanceof \MyZfcAdmin\Controller\AdminController
&& $match->getParam('action') == 'login'
) {
// if you'd rather just set the layout in your controller action just return here
// return;
// otherwise, use the configured login layout ..
$layout = $config['myzfcadmin']['login_layout_template'];
} else {
$layout = $config['myzfcadmin']['admin_layout_template'];
}
$controller->layout($layout);
}
正如您所看到的,我添加了代码以检查控制器是您的特定AdminController实例和登录操作,如果是,请设置备用模板,否则使用默认值,现在无需担心它在控制器中。
答案 1 :(得分:1)
在module.config.php
中的视图管理器的模板映射中添加您的布局像这样:
// View file paths
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array
'layout/login' => 'path_to_layout_file'
)
)
然后,在你的控制器中尝试使用setTemplate()方法设置这样的布局:
$layout = $this->layout();
$layout->setTemplate('layout/login');
编辑,以下是Zend库中的代码:
在Zend\Mvc\Controller\Plugin\Layout
内注意此方法:
/**
* Invoke as a functor
*
* If no arguments are given, grabs the "root" or "layout" view model.
* Otherwise, attempts to set the template for that view model.
*
* @param null|string $template
* @return Model|Layout
*/
public function __invoke($template = null)
{
if (null === $template) {
return $this->getViewModel();
}
return $this->setTemplate($template);
}
如果您不提供模板,则会调用此方法:
/**
* Retrieve the root view model from the event
*
* @return Model
* @throws Exception\DomainException
*/
protected function getViewModel()
{
$event = $this->getEvent();
$viewModel = $event->getViewModel();
echo '<pre>' . print_r($viewModel, true) . '</pre>';die;
if (!$viewModel instanceof Model) {
throw new Exception\DomainException('Layout plugin requires that event view model is populated');
}
return $viewModel;
}
注意print_r
语句,如果你看一下,它会告诉你:
Zend\View\Model\ViewModel Object
(
[captureTo:protected] => content
[children:protected] => Array
(
)
[options:protected] => Array
(
)
[template:protected] => layout/layout
[terminate:protected] =>
[variables:protected] => Zend\View\Variables Object
(
[strictVars:protected] =>
[storage:ArrayObject:private] => Array
(
)
)
[append:protected] =>
)
请注意[template:protected] => layout/layout
我之所以说我认为Zend默认使用该布局。
所以,使用__invoke
方法进入该文件,并在控制器中使用echo $template;die;
设置布局时执行$this->setTemplate('layout/login')
,看看它是否已经通过了// where $sm is the service manager
$config = $sm->get('config');
$config = array_merge($config, include '/path_to_config/layouts.config.php');
if (isset($config['module_layouts'][$moduleNamespace]))
{
$controller->layout($config['module_layouts'][$moduleNamespace]);
}
。然后你可以更好地追踪它。
编辑:设置多个布局。
以下是为模块设置布局的一种方法,以减少冲突或被覆盖的可能性。
'module_layouts' => array(
'_default' => 'layout/layout',
'admin' => 'layout/admin',
'foo' => 'layout/foo',
'login' => 'layout/login' // etc, etc
),
你的布局配置看起来像这样:
{{1}}