协同标志器:构建局部视图的最佳方式

2022-08-30 12:16:47

你会如何在Codeigniter中构建下面的页面?

alt text

我想过为每个部分创建单独的控制器

  1. 左侧导航
  2. 内容导航
  3. 登录名
  4. 排行榜

排除内容部分(因为这会根据左侧导航上的链接和用作某种子菜单的内容导航而变化)。所有其他部分大致保持不变

我想过做:

Class User_Profile extends Controller
{

    function index()
    {
        $this->load_controller('Left_Nav');
        $this->load_controller('Content_Nav');
        $this->load_controller('Login_Name');
        $this->load_controller('Leaderboard', 'Board');

        $this->Left_Nav->index(array('highlight_selected_page' => 'blah'));

        $this->load('User');

        $content_data = $this->User->get_profile_details();

        $this->view->load('content', $content_data);

        $this->Login_Name->index();
        $this->Board->index();
    }

}

显然,这不存在,但这种功能将是有用的。每个部分的控制器从模型中获取所需的数据,然后加载页面load_controller$this->view->load()

在所有左侧导航链接(如新闻,用户,关于我们等)中都有此代码可能会令人头疼。但话又说回来,并不是每个导航链接都有所有这些部分,所以我需要将这些部分作为“部分视图”的灵活性。

任何人都可以提出更好的方法来做到这一点吗?


答案 1

对于小于2.0的旧版本的CI,@Reinis答案可能是正确的,但是从那时起发生了很多变化,所以我想我会用我所做的事情的最新方法来回答这个问题。

其中大部分类似于@Reinis方法,也在此处描述:http://codeigniter.com/wiki/MY_Controller_-_how_to_extend_the_CI_Controller

但是,以下是我完成的更新:

步骤 1:创建一个MY_Controller.php文件并将其存储在 /application/core 中

步骤2:在您的MY_Controller.php文件中放入以下内容:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class MY_Controller extends CI_Controller {

    function __construct()
    {
        parent::__construct();
    }

    function _output($content)
    {
        // Load the base template with output content available as $content
        $data['content'] = &$content;
        echo($this->load->view('base', $data, true));
    }

}

步骤 3:创建一个基于MY_Controller.php的示例控制器,在本例中,我将创建一个欢迎.php控制器,其中包含以下内容:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Welcome extends MY_Controller {

    function __construct()
    {
        parent::__construct();
    }

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

}

设置这些控制器后,请执行以下操作:

步骤 4:在 /application/views 中创建一个基视图并将文件命名为 base.php,文件的内容应类似于以下内容:

<!DOCTYPE html>
<!--[if IE 7 ]><html lang="en" class="ie7"><![endif]-->
<!--[if IE 8 ]><html lang="en" class="ie8"><![endif]-->
<!--[if gt IE 8]><!--><html lang="en"><!--<![endif]-->
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <title></title> 
        <link rel="stylesheet" href="<?php echo base_url(); ?>stylesheets/reset.css" media="screen" />
    </head>
    <body>
        <div id="section_main">
            <div id="content">
                <?php echo $content; ?>
            </div>
        </div>
        <?php $this->load->view('shared/scripts.php'); ?>
        </div>
    </body>
</html>

步骤 5:在 /application/views 中创建另一个视图,并将此视图命名为 welcome_message.php,此文件的内容将为:

<h1>Welcome</h1>

完成所有这些操作后,您应该会看到以下输出:

<!DOCTYPE html>
<!--[if IE 7 ]><html lang="en" class="ie7"><![endif]-->
<!--[if IE 8 ]><html lang="en" class="ie8"><![endif]-->
<!--[if gt IE 8]><!--><html lang="en"><!--<![endif]-->
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <title></title> 
        <link rel="stylesheet" href="http://somedomain.local/stylesheets/reset.css" media="screen" />
    </head>
    <body>
        <!-- BEGIN: section_main -->
        <div id="section_main">
            <div id="content">
                <h1>Welcome</h1>
            </div>
        </div>
        <!-- END: section_main -->
        <script src="/path/to/js.js"></script>
        </div>
    </body>
</html>

如您所见,已放入基本模板中。<h1>Welcome</h1>

资源:

希望这有助于其他任何遇到这种技术的人。


答案 2

我不能保证这是最好的方法,但我创建了一个像这样的基本控制器:

class MY_Controller extends CI_Controller {

    public $title = '';
    // The template will use this to include default.css by default
    public $styles = array('default');

    function _output($content)
    {
        // Load the base template with output content available as $content
        $data['content'] = &$content;
        $this->load->view('base', $data);
    }

}

名为“base”的视图是一个模板(包含其他视图的视图):

<?php echo doctype(); ?>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <?php $this->load->view('meta'); ?>
    </head>
    <body>
        <div id="wrapper">
            <?php $this->load->view('header'); ?>

            <div id="content">
                <?php echo $content; ?>
            </div>

            <?php $this->load->view('footer'); ?>
        </div>
    </body>
</html>

这样做的结果是,每个控制器都将其输出包装在基本模板中,并且视图具有有效的 HTML,而不是在一个视图中打开标记,在另一个视图中关闭标记。如果我希望特定的控制器使用不同的或没有模板,我可以覆盖魔术方法。_output()

实际控制器将如下所示:

class Home extends MY_Controller {

    // Override the title
    public $title = 'Home';

    function __construct()
    {
        // Append a stylesheet (home.css) to the defaults
        $this->styles[] = 'home';
    }

    function index()
    {
        // The output of this view will be wrapped in the base template
        $this->load->view('home');
    }
}

然后,我可以在我的视图中使用它的属性,如下所示(这是填充元素的“meta”视图):<head>

echo "<title>{$this->title}</title>";
foreach ($this->styles as $url)
    echo link_tag("styles/$url.css");

我喜欢我的方法,因为它尊重DRY原则,并且页眉,页脚和其他元素只在代码中包含一次。


推荐