代码点火器调用视图中的其他控制器


Codeigniter call other controller in view

如何在一个视图中合并两个控制器。

我有两个控制器:

1.PostController

2.CommentController

帖子控制器将显示数据库中的所有帖子,并且帖子可以有注释。对于注释,我使用另一个控制器CommentController来避免DRY。在html帖子列表中,当循环时,我试图附加评论,如果存在的话,所有帖子都基于他们的ID。

在我的PostController>indexAction() am获取所有帖子

// controllers/PostController.php
/**
 * List all posts
 *
 */
public function index()
{
    $data = array(
        'posts' => $this->post->findAll(),
    );
    $this->load->view('post/index', $data);
}

以下是comment controller中列出分配post_id:的注释的方法

// controllers/CommentController.php
/**
 * List all comments assigning post id 
 *
 * @param int $post_id
 */
public function index($post_id)
{
    $data = array(
        'comments' => $this->comment->findAllByPostId($post_id), // <-- SELECT * FROM comments WHERE post_id = {post_id}
    );
    $this->load->view('comment/index', $data);
}

所以现在在post/index上午获取所有帖子:

<?php if($posts): ?>
<?php foreach ($posts as $post): ?>
    <h1> <?= $post->title; ?> </h1>
    <div> <?= $post->text; ?> </div>
    <div class="comment-list"> 
       <!-- How to call here comment controller and index($post->post_id) -->
       <!-- i can use load->view('comment/index') but with this i do nothin i need to assigning  post id
       <!-- Need somthing $commentObject->index($post->post_id) but this in MVC is not good idea --> 
    </div>
<?php endforeach() ;?>
<?php endif; ?>

还有其他解决方案吗?

我解决这个问题的方法是把所有的东西放在一个控制器Post中。但我认为这是不好的做法,因为我会把后者擦干。我需要其他ex的评论控制器(PictureController也可以有评论,我不想要DRY)

也许我的流程或组织不好?

ps。我搜索SO,但结果对我没有帮助

控制器从模型中获取数据。因此,通常情况下,任何数据库交互都会在模型中发生,然后控制器会问"你得到我的信息了吗?如果是,显示它,如果不是,做其他事情"。当所有东西都被整理好后,数据就会被发送到视图。

一个控制器可以从许多不同的模型调用,并且可以向视图发送多个数据结构。

    public function index()
    {
            // assuming you have a model called 'post'
            // check if any posts came back from the search
            if( ! $posts  = $this->post->findAll() )
            { 
                $this->_showNoPostsReturned() ; 
            } 
            // now assuming you have a model called comment 
            // in your model you will have to foreach through posts etc
           // did any comments come back? 
           elseif( ! $comments = $this->comment->returnFor($posts) )
           {
               $this->_showOnlyThe($posts) ; 
           } 
           // else we have posts and comments 
           else{ $this->_showBoth($posts,$comments) ; }
  }
  private function _showBoth($posts,$comments){
   // this is how you pass more then one data structure 
   // array, object, text, etc etc 
   // with $data['name']
   $data['posts'] =  $posts ; 
   $data['comments'] =  $comments ; 
   // and call more then one view if necessary 
   $this->load->view('post/index', $data);
   $this->load->view('comment/index', $data);
   } 

因此,这个index方法只要求从模型中获取数据,然后根据它返回的数据(如果有),它调用一个单独的私有方法,该方法可以调用适当的视图。换句话说,现在你不需要在你的视图中这样做

<?php if($posts): ?>

这是你想要避免的,因为这样的观点就是决定要展示什么。显然,某些逻辑将发生在视图中,但尽可能多的所有决策都应该发生在控制器中。

Meta

首先,我认为你确实想DRY,因为DRY的意思是"不要重复自己"。我想你已经明白了这个概念,但读到你"不想干燥"有点令人困惑;)

回答

其次:在经典的MVC方法中(CodeIgniter确实做了很多),确实让控制器处理然后传递到视图的模型(或来自它的数据)。

现在,关于如何从控制器中检索您想要的所有数据,有不同的概念,例如,真正在控制器中读取所有数据,然后将其传递给视图,而不是只传递"post"模型并让视图删除视图中的post注释。我认为两者都有正当理由,你可以决定使用哪一个(还有其他的!),尽管我更喜欢后一个。

一种替代方案可能是使用"装饰器模式"(参见维基百科),它似乎只在CodeIgniter中有一个userland实现:https://github.com/ccschmitz/codeigniter-decorator

TL;DR

您的方法很好,但您可能会研究decorator模式(见上文)。