CakePHP 2.4从插件中抛出主要的应用程序异常? (干扰requestAction?)

时间:2014-01-05 09:34:51

标签: cakephp exception layout cakephp-2.4

我正在将一个运行良好的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的元素时,异常都会中断布局。

有什么想法吗?

我会重申,在应用程序中不是插件的任何地方抛出异常时,一切都能正常运行。

1 个答案:

答案 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项目中使用了这种模式,它看起来效果很好。