CodeIgniter中包含视图的最佳方法是什么?

73
我要开始一个大型的CodeIgniter项目,并想尝试创建一些可重用的“迷你”视图,用于显示在不同页面/控制器上的数据循环等内容片段。
从主控制器的视图中调用视图是否更好?如果是,怎么做?还是应该从控制器中调用“迷你视图”,因此将视图的代码传递给主视图?

1
类似于这个问题(Laravel)- https://dev59.com/bGQm5IYBdhLWcg3w8Sne - Robin Hood
6个回答

126

在其他视图中嵌套的视图称为嵌套视图。在CodeIgniter中有两种包含嵌套视图的方式:

1. 在控制器内加载嵌套视图

预先加载视图并传递给其他视图。首先在控制器中添加以下内容:

<?php
// the "TRUE" argument tells it to return the content, rather than display it immediately
$data['menu'] = $this->load->view('menu', NULL, TRUE);
$this->load->view ('home', $data);
?>

请将<?=$menu?>放在视图中您想要菜单出现的位置。

2. 从一个视图中“加载”另一个视图

首先,在控制器中添加以下内容:
<?php
  $this->load->view('home');
?>

然后将此代码放入/application/views/home.php视图中:

<?php $this->view('menu'); ?>

<p>Other home content...</p>

关于最佳方法,我更喜欢第一种方法而不是第二种,因为使用第一种方法时,我不必混合代码,就像include php那样。虽然两种方法间接地相同,但第一种方法比第二种方法更清晰和干净!

我认为没有必要提前载入视图并传递到其他视图。看看我的解决方案。 - Rahul Chipad
1
@RahulChipad 你没有注意到评论: "TRUE" 参数告诉它返回内容,而不是立即显示它,这意味着即使提前加载,它也不会有任何影响。 - sandip
4
警告:当你以这种方式传递一个视图(使用 TRUE 参数)时,你正在将所有的视图内容转换成一个字符串。这通常能够正常工作,但一旦你有重量级数据,或者当你传递数组或JSON时,它就会出问题。 - CodeGodie
2
我不喜欢方法1,因为在“home”视图中从未正确接收$menu…如果您查看“home”,您不知道$menu来自哪里… - dsdsdsdsd
2
第二种方式更受欢迎。 - Taufik Nur Rahmanda
显示剩余3条评论

18
老实说,我更喜欢使用模板视图来加载控制器中所需的数据,这意味着较少的重复代码,并且比从视图中加载视图更好地遵循DRY原则。特别是对于标题、页脚和菜单等内容。
因此,我的模板视图可能如下所示:

template.php

$this->load->view('header',$title);
$this->load->view('sidebar',$sidebar_content);
$this->load->view('main_content',$main_content);
$this->load->view('footer');

然后在我的控制器中,我像这样传递所需的数据到模板:
$data['title'] = 'Home Page';
$data['sidebar_content']='pages/standard_sidebar';
$data['main_content'] ='pages/my_home_page'; 
$this->load->view('template',$data);

这样做有很多好处。首先,我可以拥有多个模板,例如,在我的情况下,我有两个主要的模板,一个是没有侧边栏的全页面视图,另一个是带有侧边栏的页面,我还调用if语句来决定包含哪个头部,常规的还是带有管理菜单的。

是的,我可以在每个主视图页面中包含头部、侧边栏和页脚,但这最终会导致大量重复的代码。如果例如,我想让所有页面都有一些新的东西,一些其他的小片段,使用模板,我只需将片段添加到适当的模板中即可完成。而采用另一种方法,我需要找到每个页面并在那里添加片段视图,这相当于在页面中使用CSS,浪费且不易维护。


1
我喜欢你的技术,但我不太明白其他方法如何增加编码工作量。例如,如果我想在标题视图中添加语言栏,我只需编辑标题视图而无需编辑其他内容。我错过了什么吗?顺便说一下,我是一个老编码人员,对CodeIgniter完全陌生。 - itsols
它们增加的不是编码工作量,而是重复代码。看看上面的代码。如果我没有创建一个模板,那么我将为控制器中的每个页面调用前4行。这更多地涉及模块化和易于包含/排除,而不是其他任何内容。在一个非常基本的网站上,所有页面都具有相同元素,这并不是很大的问题,甚至不值得额外的努力。但是在页面差异显著的复杂网站上,这样做可以节省很多麻烦和重复。 - Rick Calder
这不是和@sandip的答案中的方法2基本相同吗? - dsdsdsdsd
我的回答提供了对相同代码的另一种观点,并展示了将其拆分为模板的好处。注入方法是相同的,但整体视角却完全不同。三年前的答案,如果两个人提供了不同观点的相同代码,这真的很重要吗? - Rick Calder
我该如何将$data传递到头部?假设我想要传递比$title更多的内容到头部。 - Lucas Bustamante
@LucasBustamante 将传递到标题的数据变成一个数组。这样你就可以使用 $data['header_data']['title'] 和 $data['header_data']['tagline'],然后在模板中只需传递 $header_data,应该就可以正常工作了。 - Rick Calder

9

方法1

我在视图中使用此方法将包含视图插入到所需的位置。

$this->load->view('include/include_view');


方法2

或者在控制器中,您可以像这样加载多个视图:

$this->load->view('header_view');
$this->load->view('list_view');
$this->load->view('footer_view');

没有哪种方法比另一种更好,这取决于您是否需要传递一些数据(在这种情况下使用method2),或者您是否想在主视图的特定部分中包含视图(在这种情况下最好使用method1)。


METHOD 3

通过主视图将数据传递给您的包含视图

进入您的控制器:

$data['title'] = "Title";
$this->load->view('main_view',$data);

在您的观点中
$data2['title'] = $title;
$this->load->view('include/include_view',$data2);

如果您想将整个数据传递给include视图,可以按照以下方式进行操作: 在您的控制器中:

$data['nestedView']['title'] = 'title';

在您的看法中
$this->load->view('includes/included_view', $nestedView);

我会寻找传递数据的方法,但方法一似乎是更好的选择。只需要弄清如何将数据传递给它。 - David
你可以通过以下方式传递数据:$this->load->view('include/include_view',$data); 但问题在于,在控制器中,你必须将数据传递给主控制器,然后在主控制器中将数据传递给包含视图。这是一种冗长的方式,但如果需要,你可以使用它。 - Alessandro Minoccheri
有没有一种方法可以传递整个数据? - David

4
这是一种简单的在视图中包含其它视图的方法。不需要预先加载视图,只需将视图路径传递给其他视图即可。
在您的控制器中使用以下代码:
$data['middle'] = 'includeFolder/include_template_view';  //the view you want to include
$this->load->view('main_template_view',$data);  //load your main view

在main_template_view中,你可以包含其他视图:
$this->load->view($middle);

2

我认为为了更有效地解决这个问题,我已经这样做:

您可以创建一个新的帮助程序(在应用程序/ helpers中),并命名为(例如common_helpers.php,下划线很重要)。在此文件中,您可以放置所有通用的构建HTML片段的函数。

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

    function getHead(){
    require_once(APPPATH."views/common/head.php");
    }   

    function getScripts(){
    require_once(APPPATH."views/common/scripts.php");
    }

    function getFooter(){
    require_once(APPPATH."views/common/footer.php");
    }

在您的控制器中,根据MVC模式只调用一个视图,并从您的自定义助手中调用函数。
class Hello extends CI_Controller {

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

}

-1
在控制器中。
控制器。
<?php
    public function view($page = NULL)
        {
          if ( ! file_exists(APPPATH.'views/pages/'.$page.'.php'))
        {
                 $data['title'] = ucfirst($page); // Capitalize the first letter
                // Whoops, we don't have a page for that
                show_404();

        }

        $data= array(''); 
        $data['title'] = ucfirst($page); // Capitalize the first letter 
         $data['page_layout']='pages/'.$page;    
         $this->load->view('page_layout', $data);
        }
?>

在Views文件夹中创建一个名为page_layout.php的页面。
page_layout.php

//This is where you set the layout to call any view through a variable called $page_layout declared in the controller//

 <?php
     $this->load->view('header');
     $this->view($page_layout);
     $this->load->view('footer');
  ?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接