如何在一个视图中合并两个控制器。
我有两个控制器:
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模式(见上文)。