Two controllers for one view, CodeIgniter?

2019-05-21 03:45发布

问题:

Hey guys, I am new to CodeIgniter and need some help. I have a controller that formats the content area of a post. The problem is that I also need to create a sidebar that contains dynamic groups, and a right column that contains recent posts. This isn't hard, the problem I'm running into is that I want the sidebar, and right column on every page, and I don't want to recode the same bits to get the data in every controller.

What would be the best way to do this without copy/paste?

回答1:

There are a lot of ways to do this.

1) Templating: This is my preference for most cases (because my templates are complex), I render my view into a variable using something like:

$content = $this->load->view('myview', $page_data, true);

Then I load it into the template parser (fyi you could load it into another view too) like this:

$this->load->library('parser');
$data = array(
        'page_title' => 'My Page Title',
        'page_content' => $content,
        'side_bar' => side_bar(), // function which generates your side bar
        'right_col' => right_col() // function which generates your right column
        );
$this->parser->parse('my_template', $data);

Then your template is like:

<html>
<head>
<title>{page_title}</title>
</head>
<body>
    <div>{side_bar}</div>
    <div>{page_content}</div>
    <div>{right_col}</div>
</body>
</html>

2) Load another view in your view: (assumes you menu is a view not a controller) Something like this:

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

3) PHP Includes: exactly how you would do it in plain PHP (just include a url which points to a controller which returns a menu), Something like this:

<?php include("/common/sidebar"); ?>

Codeigniter will render that page and then include it.

4) AJAX.. i use this if the content in the "template" content is less important, like banners, suggested related item lists and such.



回答2:

Use PHP to generate a static HTML page, such as side_bar.html... Then you can include it on other pages.



回答3:

You could look into HMVC. It's especially suited for "widget"-type areas like you are talking about.

Essentially what you will do is create two full MVC structures - one for your sidebar and right column, including a controller, a model(if required), and a partial view. Then, you can call this controller directly from the main view to pull the required content in to the page.

To actually call it from within a view, just place the following in the markup wherever you want the sidebar to appear:

<?php echo modules::run('module/sidebar/index'); ?>

The index isn't required, but I put it there to demonstrate that you can call different methods using modules::run(). You can also pass an unlimited number of parameters to modules::run().



回答4:

In code igniter, there is an optional third parameter to $this->load->view that lets you return a rendered view as a string, which can in turn be used for assignment. What you can do is create a master template, that has all the common parts, as a very simplified example:

<html>
<head>
</head>
<body>
<?php echo $sidebar; ?>
<?php echo $content; ?>
<?php echo $right_column; ?>
</body>
</html>

Then you can create a private function in your controller to populate the dynamic content of your common parts, and combine them with your content and master template:

private function BuildTemplate($view, $data) {
   // Generate sidebar content
   $sidebar_data['...'] = 'blah blah';
   $master_data['sidebar'] = $this->load->view('sidebar', $sidebar_data, true);

   // Generate right column data
   $right_data['...'] = 'blah blah';
   $master_data['right_column'] = $this->load->view('right_column', $right_data, true);

   // Now load your content
   $master_data['content'] = $this->load->view($view, $data, true);

   // Merge it into the master template and return it
   return $this->load->view('master' $master_data, true);
}

Then in your appropriate controller method:

public function index() {
   $data['...'] = 'blah';
   echo $this->BuildTemplate('index', $data);
}

Which will pull everything together for you. You can optionally add extra arguments to BuildTemplate if you want to add things like page specific titles or scripts.



回答5:

I'm not sure if your problem is in the view, or in the (dynamic) data to be shown in the (common parts of) that view. If it's the later (as seems to suggest the phrase 'I don't want to recode the same bits to get the data in every controller'), then you have several options. For example.

  1. Put the logic to get the 'common' data in some function outside the controller, as a helper or inside some model, and call it from your controllers.

  2. Make your controllers inherit your own custom controller, that implements that data gathering function.

  3. Refactor your two controllers into a single controller, with different functions for each scenario.



回答6:

1-Create a custom library class in library folder with the below code

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

class LoadView{

   function __construct(){
    $this->CI =& get_instance();
   }
   function load_view($page){
       $this->CI->load->view('header');
       $this->CI->load->view('sidebar');
       $this->CI->load->view($page);
       $this->CI->load->view('footer');
   }

}

2-Now load this library in your controller like this

$this->load->library('loadview');

3-Now call the library method and simply insert your page name and you don't have to include header,sidebar and footer again and again as they will be dynamically included by your library.

$this->loadview->load_view('about.php');