繁体   English   中英

Codeigniter:构建部分视图的最佳方式

[英]Codeigniter: Best way to structure partial views

如何在Codeigniter中构建以下页面?

替代文字

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

  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()加载页面

在新闻,用户,关于我们等所有左侧导航链接中使用此代码可能会令人头疼。但是,然后再次并非每个导航链接都包含所有这些部分,因此我需要将这些部分作为“部分”的灵活性视图”

谁能建议更好的方法呢?

@Reinis的回答可能正确地针对小于2.0的旧版本的CI正确地点击了,但是从那以后很多都发生了变化,所以我想我会用我所做的最新方法回答这个问题。

其中大部分类似于@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的样本控制器,在这种情况下,我将在application / controllers /中创建一个welcome.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>已放入基本模板。

资源:

希望这可以帮助其他人遇到这种技术。

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

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而不是在一个视图中打开标记而在另一个视图中关闭。 如果我想让特定的控制器使用不同的模板或不使用模板,我可以覆盖magic _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');
    }
}

然后我可以在我的视图中使用它的属性(这是填充<head>元素的'meta'视图):

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

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

我的模板库可以处理所有这些。 您可以创建一个(或多个)布局文件,其中包含部分内容以及主体内容所在位置的标记。

语法简单如下:

// Set the layout: defaults to "layout" in application/views/layout.php
$this->template->set_layout('whatever') 

// Load application/views/partials/viewname as a partial
$this->template->set_partial('partialname', 'partials/viewname');

// Call the main view: application/views/bodyviewname
$this->template->build('bodyviewname', $data); 

简单吧?

将其中的一些放入MY_Controller,它更容易。

你考虑过模板吗? 有很多不错的搜索 - 查看CI维基。

模板或多或少地完全符合您的要求。 您可以定义一个主模板和“部分”,每次都会为您加载这些模板和“部分”

不想插入太多,所以这可能会让你开始 - CI中的模板库

我会制作一个MY_Controller来处理这一切。 您可以使用布局(模板)/导航库来生成所有布局,导航,显示/突出显示所选菜单项,加载视图等。

如果你为每个页面部分使用一个控制器,我会说这不是正确的方法。 您可以为此使用视图和嵌套视图。

我喜欢Phil Sturgeon提到的。 虽然它被认为是非常复杂的我真的很喜欢magento的模板结构。

灵感来自于这种结构化方式,我创造了我的逻辑,(它根本不是很好,但它很简单,也许我可以覆盖 - >视图加载器并使它接受某种对象作为模板名称和比根据需要加载结构)

第一 :必须非常负责任地使用这种方法(您可以在模板所需的控制器/方法中准备数据!

第二 :模板需要准备和正确组织。

这就是我做的:

  • 在每个控制器中我都有Array类型的属性,如下所示:

     class Main extends CI_Controller { public $view = Array( 'theend' => 'frontend', 'layout' => '1column', 'mainbar' => array('content','next template file loaded under'), 'sidebar' => array('generic','next template file loaded under'), 'content' => '', ); 
  • 在我想要使用以前的结构的每个方法中,如果我想稍微更改它,我会这样写:

     public function index() { $data['view'] = $this->view; // i take/load global class's attribute $data['view']['mainbar'] = Array('archive','related_posts'); // i change mainbar part of it // i add/load data that i need in all those templates that are needed $data['view'] also my using same Array $data['my_required_data_that_i_use_in_template_files'] = 1; $this->load->view('main',$data); // } 

第三个在/ application / view文件夹中我有类似的结构

/view/main.php <-- which basically just determines which side's wrapper of web to load (frontend or backend or some other)

/view/frontend/wrapper.php

/view/backend/wrapper.php

/view/mobile/wrapper.php   <-- this wrappers are again another level of structuring for ex:

/view/backend/layouts/   <-- inside i have templates different layouts like 1column.php 2columns-left (have left side is narrow one),2columns-right,3columns... etc...

/view/backend/mainbar/   <-- inside i have templates for mainbar in pages

/view/backend/mainbar/.../ <-- in the same way it's possible to add folders for easily grouping templates for example for posts so you add for example

    /view/backend/mainbar/posts/  <-- all templates for creating, editing etc posts... 

    /view/backend/sidebar/   <-- inside i have templates for sidebar in pages

    /view/backend/...other special cases.... like dashboard.php

在/app/view/main.php文件看起来是这样的:

if ($view['theend'] == "frontend")
{
$this->load->view('/frontend/wrapper');
} elseif ($view['theend'] == "backend")
{
$this->load->view('/backend/wrapper');
}

第五个包装器是简单的一些PHP在结构化的HTML中,你有头(加载HTML标题,标题等...)标题/标题(如果有任何传递$ data ['view'] ['headers']变量加载在标题中/ array)布局(在布局文件中加载,只是具有下一级加载文件的新html结构化文件)页脚/页脚(如果有任何传入的$ data ['view'] ['footers']变量,则在页脚中加载)脚本(在标记之前加载分析/ facebook脚本等脚本)

第六,所以以同样的方式,布局也将加载在public $ view = Array(....)中指定的mainbar / sidebar内容中

如果我需要某种方法,我只是覆盖public $ view = Array(...)属性的一部分,并且我只覆盖不同的部分。

它完成了这样的事情:

public function index()
{
    $data['view'] = $this->view;  // i take/load global class's attribute
    $data['view']['mainbar'] = Array('archive','related_posts'); // i change mainbar part of it
// i add/load data that i need in all those templates that are needed $data['view'] also my using same Array  $data['my_required_data_that_i_use_in_template_files'] = 1;
    $this->load->view('main',$data); //
}

最终加载如下:

  1. $这 - >负载>视图( '主',$数据); < - 加载/app/view/main.php并传递$ data $ data有节点'view'($ data ['view']),其中有子节点确定其他重要的东西,比如:什么是结束什么布局,什么标题,什么页脚等...

  2. 使用$ data ['view'] ['theend']中定义的数据,它会加载正确的包装器

  3. 再次在包装中使用$ data ['view'] ['layout']中的数据,它会加载其他更深层次的结构,如布局......
  4. 布局,使用相同的$ data ['view'] ['mainbar'],$ data ['view'] ['sidebar']并抓住其他重要部分加载,如主栏模板,侧边栏模板......

就是这个......

ps我很抱歉没有使用数字,但stackoverflow系统是如此奇怪,而不是显示3.它显示我1 ..因为你看到我有一些嵌套列表...

我所做的(在Kohana 2中)有1个模板,包含所有子部分(如左侧菜单,顶部标题),以及一个控制器,用于填充将在模板中替换的变量。

然后,每个子部分的变量可以由控制器本身调用的函数生成。 您还可以将这些函数放在单独的控制器类的构造函数中,您的每个控制器都会扩展该控制器,以便它们自动运行并设置为类变量以便于访问。

对于稍微好一点的模板,您可以将子部分放在单独的文件中,大模板包含它们:

<?php include 'leftMenu.php'; ?>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM