我正在将一个运行良好的CakePHP(v 2.44)应用程序转换为插件,当我在插件中的控制器中抛出异常时,我得到了最奇怪的行为:异常处理程序/渲染器正在启动在app / View / Layouts / mylayout.ctp中使用我的主站点布局,然后使用app / View / Layouts / error.ctp中的默认布局中断它。这是一个摘录:
<div><ul><li class="jsdnavpopup blog-menu-categories">
<a href='/blog/categories'>All Categories</a><nav>
<!DOCTYPE html PUBLIC "{trimmed for space}">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CakePHP: the rapid development php framework:Error Page</title>
如果您注意到在Cake的组合布局中正好发送了一个新标题。在我的布局中断的位置,我加载了元素,元素使用requestAction(在我的开发环境中没有缓存)。如果我删除元素,那么我的布局会被渲染得更多,直到遇到使用requestAction的下一个元素。这些requestAction调用不会从引发异常的插件请求操作。
我正在使用app / Config / core.php中的所有默认错误处理程序。唯一不同的是在错误视图中指定$ this-&gt;布局。
现在,如果我在插件的View文件夹中重新创建原始错误布局和视图,那么事情就像我期望的那样。但是出于实验目的,我将主站点布局的重命名副本放在那里,同样的事情。每当遇到使用requestAction的元素时,异常都会中断布局。
有什么想法吗?
我会重申,在应用程序中不是插件的任何地方抛出异常时,一切都能正常运行。
答案 0 :(得分:0)
这是我如何做到的(按照对OP问题的评论中的要求)
在我的布局中,我将以下代码放在我想要显示顶部菜单的位置:
<?php echo $this->element('Menu.top_navigation'); ?>
这非常简单,并允许我的团队中的HTML设计人员将菜单放在任何他们想要的位置 当然还有更多的事情发生在幕后。以下是您需要执行此操作所需的其他文件:
插件/菜单/查看/元件/ top_navigation.ctp:
$thisMenu = ClassRegistry::init('Menu.Menu');
$menus = $thisMenu->display_menu_widget(array('position'=> 'top'));
echo $this->element('Menu.display_ul', array('menus' => $menus));
请注意,这只是一个包装器 - 您可以为页脚导航创建更多这些内容,甚至可以创建一个允许您作为参数传递位置的元素。
插件/菜单/查看/元件/ display_ul.ctp:
<?php
if(empty($depth)){
$depth = 0;
}
switch($depth){
case 0:
$classes = "dropdown";
break;
default:
$classes = "";
break;
}
?>
<ul class="<?php echo $classes ?> depth_<?php echo $depth ?>">
<?php foreach ($menus as $menu): ?>
<li>
<a href="<?php echo $menu['MenuItem']['url']; ?>">
<?php echo $menu['MenuItem']['title']; ?>
</a>
<?php
if(count($menu['children']) > 0){
echo $this->element(
'Menu.display_ul',
array(
'menus' => $menu['children'],
'depth' => $depth + 1
)
);
}
?>
</li>
<?php endforeach; ?>
</ul>
插件/菜单/型号/ Menu.php:
/**
* display_menu_widget method
*
* @param array $options
* @return void
*/
public function display_menu_widget($options = array()) {
$defaults = array(
'position' => 'top'
);
$settings = array_merge($defaults, $options);
$this->recursive = 0;
$menuItems = array();
$conditions = array(
'Menu.position' => $settings['position']
);
$menuDetails = $this->find('first', array('recursive' => -1, 'conditions' => $conditions));
$menuPosition = $menuDetails[$this->alias]['position'];
$parentId = $menuDetails[$this->alias][$this->primaryKey];
$conditions = array(
$this->MenuItem->alias . '.menu_id' => $parentId
);
$this->MenuItem->recursive = 0;
$cacheName = 'default' . 'ModelMenuItem';
$cacheKey = $this->generateCacheName(array('type' => 'threaded', 'conditions' => $conditions));
$menuItems = Cache::read($cacheKey, $cacheName);
if(empty($menuItems) || PWFunctions::forceCacheFlush()){
$menuItems = $this->MenuItem->find('threaded', array('conditions' => $conditions));
Cache::write($cacheKey, $menuItems, $cacheName);
}
return $menuItems;
}
菜单功能可能比您需要的更多,我正在使用一些积极的缓存例程来减少数据库负载,我建议在担心缓存之前只使用该功能的骨架。
这个解决方案对我来说效果很好,而且我认为这是违反MVC概念的解决方案 - 当你作为设计师时,你处于HTML模式并且想“嘿我需要显示顶层菜单”然后它只是您视图中的一行,您无需担心修改控制器或模型。
我在目前的CakePHP项目中使用了这种模式,它看起来效果很好。