【问题标题】:CodeIgniter menu/nav dilemmaCodeIgniter 菜单/导航困境
【发布时间】:2012-10-22 16:21:16
【问题描述】:

我正在尝试 CodeIgniter 和整个 MVC 模式。我已经安装了Colin Williams' Template library,但是当我试图想出包含两个菜单/导航的正确方法时,我遇到了困难:一个是通用的(可能在顶部),一个是每个控制器特定的侧边栏。

无论哪种方式,它们的位置都不相关,我正在考虑代码的一般结构。现在我的模型中有一个函数get_menu(),并且在为侧边栏加载部分模板视图时,它的返回值作为参数给出。还是应该在控制器中进行?

我的一个朋友建议我不要使用 MY_Controller 扩展默认控制器或模型,但我不知道何时实现常规菜单?或者我应该在模板配置文件中硬编码吗?

我找不到此类任务的指南。无论我走到哪里,我都会找到一个新的解决方案,其中许多并不漂亮,其他很多都有很多重复的代码。

编辑。我已经更新了我的代码。我还没有决定如何编写顶部导航(可能在MY_Controller 中,以便我可以突出显示当前页面)。

MY_Controller.php

abstract class MY_Controller extends CI_Controller {
    protected $_nav;

    const CONTENT_REGION = 'content';
    const NAV_REGION = 'nav';
    const TITLE_REGION = 'title';

    const SIDEBAR_NAV_TEMPLATE = 'templates/sidebar_nav';

    public function __construct() {
        parent::__construct();
        $this->_load_nav();
    }

    abstract protected function _get_nav();

    protected function _load_nav() {
        $this->_nav = array('nav' => $this->_get_nav());
    }

    protected function _render() {
        $args = func_get_args();
        $n = func_num_args() - 1;

        if ($n < 2) {
            return;
        }

        $this->template->write(self::TITLE_REGION, $args[0]);

        for ($i = 1; $i < $n; $i++) {
            $this->template->write_view(self::CONTENT_REGION, $args[$i], $args[$n]);
        }

        $this->template->write_view(self::NAV_REGION, self::SIDEBAR_NAV_TEMPLATE, $this->_nav);
        $this->template->render();
    }

    protected function _set_active_view($active) {
        if ($active !== null && isset($this->_nav['nav'][$active])) {
            $this->_nav['nav'][$active]['class'] .= ' active';
        }
    }
}

collection.php

class Collection extends MY_Controller {
    public function __construct() {
        parent::__construct();
        $this->load->model('collection_model');
    }

    protected function _get_nav() {
        return array(
            'collection/view' => array(
                'href'  => 'collection/view',
                'value' => 'View collection',
                'class' => 'icon-film'
            ),
            'collection/add' => array(
                'href'  => 'collection/add',
                'value' => 'Add title',
                'class' => 'icon-plus-sign'
            )
        );
    }

    public function index() {
        $this->view();
    }

    public function view() {
        $data['list'] = $this->collection_model->get_list();
        $this->_set_active_view('collection/view');
        $this->_render('View Collection', 'collection/view', $data);
    }
}

sidebar_nav.php

<ul class="nav nav-list bs-docs-sidenav">
    <?php

    foreach ($nav as $item) {
        echo '<li';

        if ($item['class'] !== null || $item['class'] !== '') {
            echo ' class="' . $item['class'] . '"';
        }

        echo '><a href="' . $item['href'] . '">' . $item['value'] . '</a></li>';
    }

    ?>
</ul>

这看起来怎么样?我可能会在MY_Controller 中编写一个函数_render($title, $view, $data) 来完成所有模板的工作。你怎么看?

我一直在考虑的另一个解决方案是删除 _get_nav() 并从配置文件中加载所需的导航数据,但我不知道该怎么做。

【问题讨论】:

  • 不幸的是,CI 并没有真正实现 MVC 模式。视图不是模板,模型是一个层,控制器不应该将数据从模型层发送到模板。我能建议的最好的方法是阅读this article 并研究实现真实视图的方法。
  • Codeigniter 是一个 MVC 框架。我们可以设计自己的模板并将其用作视图。这就是我在 thephpcode.com 的 Codeigniter 代码生成器中使用它的方式。将视图定义为模板并将内容视图名称传递给它并显示从内容视图名称加载的内容。

标签: php codeigniter navigation


【解决方案1】:

你的“伙伴”有什么可能的理由告诉你不要扩展控制器类?这种重复的东西正是该功能的用途...使用 getMenu 和您将在整个站点中经常使用的其他功能创建 MY_Controller,然后将集合扩展为 MY_Controller 而不是 CI_Controller。

我们不仅扩展 CI 控制器,还将 MY_Controller 扩展到 User_Controller 和 Admin_Controller 以包含仅对这些用户可用的特定功能。

我真的无法想象为什么有人会告诉你不要那样做。

【讨论】:

  • 好吧,也许他毕竟不是我的“伙伴”,哈哈。他也是向我推荐CI的人,所以我觉得他可能对这个主题有所了解。我的 OOP 直觉告诉我要扩展课程。 MY_Controller 中的 get_menu() 用于一般(顶部)菜单,然后将页面特定(侧边栏)菜单功能放在哪里?在控制器中作为模型应该只处理数据库?
  • 创建MY_Model 也是明智之举?万一将来我想在所有页面上进行一些数据库查询?
  • 是的,MY_Model 没什么问题,我们的应用程序中扩展了多个核心类和库。基本上你想要做的是将 DRY(不要重复自己)与 MVC 一起应用,所以如果逻辑表明扩展库或核心类更有意义,那就去做吧。这就是 CI 允许扩展开始的原因。我们尝试根据需要为每个数据库表和控制器创建一个模型(不是每页一个,但有些人会这样做)。
  • 好的,但是菜单功能应该保留在控制器中,除非它与数据库相关,是吗?所以get_top_menu()MY_Controller 中的抽象get_sidebar_menu() 强制扩展类来实现get_sidebar_menu()
  • 是的。顺便说一句,我假设像这样的整个菜单方案是您正在使用的这个模板的一部分。我构建了自己的模板,所以像这样的静态菜单只是内置在它们需要在 HTML 中的位置。
猜你喜欢
  • 1970-01-01
  • 2014-03-08
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
  • 2018-02-14
  • 2017-05-23
  • 2016-06-23
  • 1970-01-01
相关资源
最近更新 更多