0

大家,早安。最近我读到一篇关于 mvc 模式的文章,说大多数 php 框架都错误地实现了 mvc 模式。 php master mvc 模式第 1 部分 php master mvc 模式第 2 部分 阅读完这篇文章并查看该实现之后,出现了一个问题。究竟如何在视图中调用模型中调用的方法?我想说的是这个。这是文章中的一段代码。

<?php
$model = $_GET['model'];
$view = $_GET['view'];
$controller = $_GET['controller'];
$action = $_GET['action'];

if (!(empty($model) || empty($view) || empty($controller) || empty($action))) {
    $m = new $model();
    $c = new $controller($m, $action);
    $v = new $view($m);
    echo $v->output();
} 

假设我们在阅读文章后编写了这个设计模式的一个小实现,我们有以下代码:

<?php
class Index extends Controller
{
   public function __construct(IndexModel $model, $action)
   {
       $this->model = $model;
   }
   public function someAction($id)
   {
       $this->model->getData($id);
   }
}
class Index extends View
{
   public function __construct(IndexModel $model, $action)
   {
       $this->model = $model;
   }
   public function someAction()
   {
       $this->model->getData();
   }
}
class Index extends Model
{
   public function __construct()
   {
        //Some Code Here
   }
   public function someAction()
   {
       // Inserting Data into database.
   }
}

如您所见,我们在控制器和视图中调用相同的方法来从数据库中获取数据。但是,如果我正确地知道视图应该处理控制器的工作,那么 $id 在视图中再次解析它或类似的东西是不正确的。那么如何解决呢?

4

1 回答 1

4
  1. 控制器和模型的各个部分之间没有 1:1 的相关性(注意:不是“模型”,而是_the model_ 的一部分)。仅仅因为你有一个“索引控制器”并不意味着你需要一个“索引模型”和“索引视图”。
  2. M、V 和 C 不是一起构建的。构造控制器,然后决定加载/构造/调用哪个模型方法以及哪个视图应该响应请求。
    1. 讨论了控制器是否应该调用视图,或者模型是否应该“更新”视图。由于 Web 请求是短暂的,并且没有“恒定”视图,因此后者在 PHP 中意义不大;它更适合原始 SmallTalk 或 Obj-C 或类似环境。
  3. 第一个代码片段对empty(见这里)的使用很糟糕,同样,不应该将所有部分构建在一起。

MVC 应该这样处理:

  • 模型就是 应用程序。它不仅仅是一个“数据处理程序”或“数据存储”,它还是核心应用程序。应用程序所做的一切,业务逻辑明智,都是“模型”。这包括发送电子邮件通知、数据库维护工作以及诸如此类的辅助性工作,它们都在模型中。
  • 视图负责产生各种形式的输出。视图应该能够与模型交互以获取完成工作所需的数据。数据不应该被“推入”视图,视图应该能够“拉”出它需要的数据;否则视图外部的东西需要知道视图需要什么数据,这意味着视图逻辑不再自包含在视图中。
  • 控制器只是用来调用正确的模型方法和视图以响应传入请求的一小部分粘合剂。

我通常像这样构造这些部分:

  • 该模型由多个部分组成,包括数据存储处理程序、“原语”(对单个业务对象建模的类)和“服务”。“服务”包含您的应用程序可以执行的所有“操作”并形成模型 API。每当您想在应用程序中“做”某事,例如“注册用户”或“获取日期范围 X 到 Y 的所有记录”时,服务 API 中都有一种专门的方法。只需查看此服务 API,您就应该能够枚举您的应用程序“所做”的所有事情。
  • 有一个对象是“调度程序”或“服务定位器”,或者只是一个依赖注入容器,它简化了这些服务类的实例化并允许有人调用它们。控制器获得其中之一,视图也是如此。
  • 有一个路由器根据 URL 执行一些“粗略路由”,调用控制器方法。控制器进一步查看请求的细节并决定调用模型方法和/或以视图响应。
  • 视图可能会根据请求的具体情况决定呈现某些数据的最佳方式,例如是否使用 HTML 页面或 JSON 数据块进行响应。是的 RESTful 服务。

在粗略的伪代码中:

$r = new Router;
$r->route($_GET, $_POST, $_SERVER); // or something like that

这发送到类似的东西:

class FooController {

    public function __construct(ServiceLocator $services) { ... }

    public function bar(Request $request) {
        $request->assertIsPost();
        $this->services->locate('Baz')->froogleTheWibbles($request->getPostParams());
        (new BarView($this->services))->displayWibbles($request);
    }

}

class BarView {

    public function __construct(ServiceLocator $services) { ... }

    public function displayWibbles(Request $request) {
        switch ($request->accepts()) {
            case 'html' :
                $this->loadTemplate(...);
                ...
            case 'json' :
                echo json_encode($this->services->locate('Baz')->getWibbles());
        }
    }

}

模型做它需要做的任何事情......

class Baz {

    public function froogleTheWibbles(array $data) {
        foreach ($data as $wibbleData) {
            $wibble = new Wibble($wibbleData);
            $this->wibbleStore->save($wibble);
        }
        ...
    }

}

MVC 没有“一个答案”,重要的部分是模型包含您的应用程序“所做”的一切,独立于输入和输出,视图可以根据请求尽可能独立地产生正确的输出,而控制器只是其中的一小部分处理输入条件的胶水。有多种方式可以实现这一点。重要的设计原则应该是实现视图和控制器可互换以适应不同的条件(网页、JSON API、XML API、SOAP API、CLI 调用、ZeroMQ 节点等),但“模型”不是。

于 2013-06-24T08:50:29.277 回答