简短回答:将模型传递给控制器和视图。
长答案:在 MVC 中,控制器不会“从模型加载数据然后将该数据传递给视图”。视图与模型有直接关系,并从中请求数据。请参阅:MVC 应该如何在 CodeIgniter和http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller中工作:“视图从模型请求它需要的信息生成输出表示。”
因此,要启用松散耦合,请完全独立地启动模型视图和控制器,并将它们相互传递。
这允许严格分离 MVC 提倡的关注点,并允许您将任何组件与任何其他组件重用,因为没有任何东西是硬编码的。
就像是:
$model = new Model;
$controller = new Controller($model);
$view = new View($model, $controller);
echo $view->output();
控制器不应选择视图,也不应选择模型。通过将此责任放在控制器中,控制器不能与其他视图或模型重用。
编辑:我已更新此内容以回答 tresko 关于视图为何需要了解其控制器的评论。
视图需要控制器以避免将控制器硬编码到视图中。这是为了让视图知道它在当前上下文中与哪个控制器配对并可以回发给它。
事件(用户操作)在视图中触发,需要由控制器处理。
有3种方法:
1)硬编码视图:控制器关系,在网络上这是通过使用来实现的<a href="/some/hardcoded/route"
;或<a href="' . $this->router->create('someController, 'action') . '>'
这消除了将视图与任何其他不希望的控制器一起使用的可能性。
2)将控制器传递给视图并让视图知道其事件将被触发到哪个控制器。在网络上,使用这种方法,视图还需要一个路由器,它将控制器操作转换为路由。例如<a href="' . $this->router->getRoute($this->controller, 'action') . '>'
3)将视图传递给控制器并让控制器在视图上设置操作:(控制器代码)$this->view->setEvent('buttonClick', $this->router->getRoute($this, 'action'))
...(视图代码)<a href="' . $this->getEvent('buttonClick') . '>'
这些,
1) 是最不可取的,因为它严重影响了灵活性。视图只能在非常特定的控制器上调用操作。
2) 对开发人员来说是最少的工作量,但每个控制器都需要一个特定的接口。
3)这提供了最大的技术灵活性,但开发人员需要做更多的工作,并且控制器需要了解很多关于其视图的信息,除了 API 之外,它还必须知道视图中可用的事件。如果一个视图被更新并且有一个新的动作,每个控制器都需要被更新来解释它。这也适用于 2),但是因为 2 可以使用接口轻松处理,所以跟踪使用它的每个类要容易得多。
在我看来,2 和 3 都是很好的方法,但 2 更好,因为它允许更健壮的系统并允许最多的重用,缺点是控制器必须实现特定的接口。3 允许控制器有任何接口,但它必须知道很多关于它的视图。
CakePHP 和其他流行的框架在他们的示例中倾向于对关系进行硬编码(例如http://book.cakephp.org/2.0/en/views.html),echo $this->Html->link('edit', array( 'action' => 'edit', $post['Post']['id'])); ?>
链接只能转到“编辑”控制器。这严重影响了重用。