简体   繁体   English

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

[英]Codeigniter: Best way to structure partial views

How would you structure the below page in Codeigniter? 如何在Codeigniter中构建以下页面?

替代文字

I thought about creating seperate controllers for each section 我想为每个部分创建单独的控制器

  1. Left nav 左导航
  2. Content nav 内容导航
  3. Login name 登录名
  4. Leaderboard 排行榜

Excluding the content section (as this changes depending on the link on the left nav and content nav used as a kinda sub-menu). 排除内容部分(因为此更改取决于左侧导航栏和内容导航栏中用作有点子菜单的链接)。 All the other sections remain roughly the same 所有其他部分保持大致相同

I thought about doing: 我想过:

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();
    }

}

Obviously this load_controller does not exist but this functionaility would be useful. 显然这个load_controller不存在,但是这个功能很有用。 The controller for each section gets the data required from the model and then loads the page through $this->view->load() 每个部分的控制器从模型中获取所需的数据,然后通过$this->view->load()加载页面

It could be a headache to have this code in all the left nav links like News, Users, About Us, etc.. But then again not every nav link has all those sections so I need that flexability of having the sections as a "partial view" 在新闻,用户,关于我们等所有左侧导航链接中使用此代码可能会令人头疼。但是,然后再次并非每个导航链接都包含所有这些部分,因此我需要将这些部分作为“部分”的灵活性视图”

Can anyone suggest a better way of doing this? 谁能建议更好的方法呢?

@Reinis answer probably hit the spot correctly for older versions of CI less than 2.0 however alot has changed since then, so I thought I'd answer this question with an up to date method of what I've done. @Reinis的回答可能正确地针对小于2.0的旧版本的CI正确地点击了,但是从那以后很多都发生了变化,所以我想我会用我所做的最新方法回答这个问题。

Most of it is similar to @Reinis method and also described here: http://codeigniter.com/wiki/MY_Controller_-_how_to_extend_the_CI_Controller 其中大部分类似于@Reinis方法,也在这里描述: http ://codeigniter.com/wiki/MY_Controller_-_how_to_extend_the_CI_Controller

However here are the updates ive done: 不过这是我做过的更新:

Step 1: Create a MY_Controller.php file and store it in /application/core 步骤1:创建一个MY_Controller.php文件并将其存储在/ application / core中

Step 2: In your MY_Controller.php file put in the following contents: 第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));
    }

}

Step 3: Create a sample controller to base off of MY_Controller.php, in this case I will create a welcome.php controller inside of application/controllers/ with the following content: 步骤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');
    }

}

Once you have these controllers set, do the following: 设置好这些控制器后,请执行以下操作:

Step 4: Create a base view inside of /application/views and name the file base.php, the content of the file should be similar to this: 步骤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>

Step 5: Create another view in /application/views and name this view welcome_message.php, the content of this file will be: 步骤5:在/ application / views中创建另一个视图并将此视图命名为welcome_message.php,该文件的内容将为:

<h1>Welcome</h1>

Once, all this is complete, you should see the following output: 完成所有这些后,您应该看到以下输出:

<!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>

As you can see <h1>Welcome</h1> was put into the base template. 如您所见, <h1>Welcome</h1>已放入基本模板。

Resources: 资源:

Hope this helps anyone else coming across this technique. 希望这可以帮助其他人遇到这种技术。

I can't vouch that this is the best approach, but I create a base controller like this: 我不能保证这是最好的方法,但我创建了一个这样的基本控制器:

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);
    }

}

The view called 'base' is a template (a view that includes other views): 名为“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>

What this achieves is that every controller wraps its output in the base template, and that views have valid HTML instead of opening tags in one view and closing in another. 这实现了每个控制器将其输出包装在基本模板中,并且该视图具有有效的HTML而不是在一个视图中打开标记而在另一个视图中关闭。 If I'd like a specific controller to use a different or no template, I could just override the magic _output() method. 如果我想让特定的控制器使用不同的模板或不使用模板,我可以覆盖magic _output()方法。

An actual controller would look like this: 实际的控制器看起来像这样:

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');
    }
}

Then I could use its properties in my views like this (this is the 'meta' view that populates the <head> element): 然后我可以在我的视图中使用它的属性(这是填充<head>元素的'meta'视图):

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

I like my approach because it respects the DRY principle and the header, footer and other elements get included just once in the code. 我喜欢我的方法,因为它尊重DRY原则,页眉,页脚和其他元素只包含在代码中一次。

My Template library can handle all of this. 我的模板库可以处理所有这些。 You create a single (or multiple) layout file(s) that contain the partials and a tag for where the main body content will go. 您可以创建一个(或多个)布局文件,其中包含部分内容以及主体内容所在位置的标记。

Syntax as simple as: 语法简单如下:

// 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); 

Simples right? 简单吧?

Put some of that into MY_Controller and its even easier. 将其中的一些放入MY_Controller,它更容易。

have you considered templates? 你考虑过模板吗? There are many decent ones available with a little searching - check the CI wiki. 有很多不错的搜索 - 查看CI维基。

templates do more or less exactly what you are after. 模板或多或少地完全符合您的要求。 You define one master template and "sections", and these are loaded for you each time 您可以定义一个主模板和“部分”,每次都会为您加载这些模板和“部分”

don't want to plug too much so this might get you started - template libraries in CI 不想插入太多,所以这可能会让你开始 - CI中的模板库

I would make a MY_Controller to take care of all this. 我会制作一个MY_Controller来处理这一切。 You can top it with a layout(template)/navigation library to generate all the layouts, navigation, showing/highlighting selected menu item, loading views etc. 您可以使用布局(模板)/导航库来生成所有布局,导航,显示/突出显示所选菜单项,加载视图等。

I'd say it's not the right way to do it, if you're using a controller for each page section. 如果你为每个页面部分使用一个控制器,我会说这不是正确的方法。 You can to make use of views and nested views for that. 您可以为此使用视图和嵌套视图。

I like what Phil Sturgeon mentioned. 我喜欢Phil Sturgeon提到的。 Although it's considered as very complicated i really liked template structure that magento have. 虽然它被认为是非常复杂的我真的很喜欢magento的模板结构。

Inspired with that way of structuring i made my logic, (which is not great at all but it's simple as it can be,. and perhaps maybe i could override ->view loader and make it accept some kind of object as a template name and than load the structure as required) 灵感来自于这种结构化方式,我创造了我的逻辑,(它根本不是很好,但它很简单,也许我可以覆盖 - >视图加载器并使它接受某种对象作为模板名称和比根据需要加载结构)

first : This approach must be used very responsibly (you mus prepare data in controller/method that your templates require! 第一 :必须非常负责任地使用这种方法(您可以在模板所需的控制器/方法中准备数据!

second : Template needs to be prepared and structured properly. 第二 :模板需要准备和正确组织。

This is what i do: 这就是我做的:

  • in every controller i have attribute of Array type, something like this: 在每个控制器中我都有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' => '', ); 
  • In every method for which i want to use previous structure, and if i want to change it a bit i write it like this: 在我想要使用以前的结构的每个方法中,如果我想稍微更改它,我会这样写:

     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); // } 

third In /application/view folder i have structure like 第三个在/ 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

forth file in /app/view/main.php looks something like: 在/app/view/main.php文件看起来是这样的:

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

fifth wrapper is simple some php in structured HTML where you have head (loading html headers, title etc...) header/headers (loading in headers if there are any in passed $data['view']['headers'] variable/array) layout (loads in layout file that simply have new html structured file with next level of loading files) footer/footers (loading in footers if there are any in passed $data['view']['footers'] variable) scripts (loading inscripts like analytics/facebook scripts just before tag) 第五个包装器是简单的一些PHP在结构化的HTML中,你有头(加载HTML标题,标题等...)标题/标题(如果有任何传递$ data ['view'] ['headers']变量加载在标题中/ array)布局(在布局文件中加载,只是具有下一级加载文件的新html结构化文件)页脚/页脚(如果有任何传入的$ data ['view'] ['footers']变量,则在页脚中加载)脚本(在标记之前加载分析/ facebook脚本等脚本)

sixth So in the same way, layout would be also loading in mainbar/sidebar content that is specified in public $view = Array(....) 第六,所以以同样的方式,布局也将加载在public $ view = Array(....)中指定的mainbar / sidebar内容中

If i need in some method, i simply override part of public $view = Array(...) attribute, and i override just part that is different. 如果我需要某种方法,我只是覆盖public $ view = Array(...)属性的一部分,并且我只覆盖不同的部分。

it's done something like this: 它完成了这样的事情:

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); //
}

FINALLY Load goes like this: 最终加载如下:

  1. $this->load->view('main',$data); $这 - >负载>视图( '主',$数据); <-- Loads /app/view/main.php and passes $data $data has node 'view' ($data['view']) and in it it has sub nodes which determines other important things like: what is the end, what layout, what headers, what footers etc... < - 加载/app/view/main.php并传递$ data $ data有节点'view'($ data ['view']),其中有子节点确定其他重要的东西,比如:什么是结束什么布局,什么标题,什么页脚等...

  2. Using defined data in $data['view']['theend'] it loads proper wrapper 使用$ data ['view'] ['theend']中定义的数据,它会加载正确的包装器

  3. Again using data in $data['view']['layout'] further in wrapper it loads other, deeper structures like layout... 再次在包装中使用$ data ['view'] ['layout']中的数据,它会加载其他更深层次的结构,如布局......
  4. layout, uses same $data['view']['mainbar'], $data['view']['sidebar'] and catch other important parts to load like mainbar templates, sidebar templates ... 布局,使用相同的$ data ['view'] ['mainbar'],$ data ['view'] ['sidebar']并抓住其他重要部分加载,如主栏模板,侧边栏模板......

That is about it... 就是这个......

ps I'm so sorry for not using numbers, but stackoverflow system is so strange that instead of showing 3. it shows me 1.. as you see i had some nested lists... ps我很抱歉没有使用数字,但stackoverflow系统是如此奇怪,而不是显示3.它显示我1 ..因为你看到我有一些嵌套列表...

What I've done (in Kohana 2) is have the 1 template with all the sub sections (like left menu, top header), and a single controller that populates the variables that will be replaced in the template. 我所做的(在Kohana 2中)有1个模板,包含所有子部分(如左侧菜单,顶部标题),以及一个控制器,用于填充将在模板中替换的变量。

Then, the variables for every sub-section can be generated by functions called in the controller itself. 然后,每个子部分的变量可以由控制器本身调用的函数生成。 You can also have those functions be in a separate controller class's constructor, with every controller of yours extending that one so they're automatically ran and set as class variables for easy access. 您还可以将这些函数放在单独的控制器类的构造函数中,您的每个控制器都会扩展该控制器,以便它们自动运行并设置为类变量以便于访问。

For slightly nicer templates you can have the subsections in separate files, and the big template include them: 对于稍微好一点的模板,您可以将子部分放在单独的文件中,大模板包含它们:

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

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

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