简体   繁体   English

如何正确地将数据从控制器传递到视图?

[英]How to correctly pass data from controller to view?

My current implementation: 我目前的实施:

class SomeController extends AppController
{
    function someaction()
    {   
        $d['text'] = "ahoy!";
        $this->render("someactionView", $d);
    }
}

And in AppController : AppController

function render($file, $data = "")
{
    require "views/" . $file . ".php";
}

And the $data will be available in the views file. $data将在views文件中提供。 Is this a correct implementation? 这是正确的实施吗? Are there any fallacies with this implementation? 这种实现有什么谬误吗?

And the $data will be available in the views file. $data将在views文件中提供。 Is this a correct implementation? 这是正确的实施吗? Are there any fallacies with this implementation? 这种实现有什么谬误吗?

Basically you do implement it like the most frameworks do. 基本上你像大多数框架一样实现它。 There's a couple of problems with that: 这有几个问题:

  • A controller takes an input and sends an output (which breaks the Single-Responsibility Principle) 控制器接受输入并发送输出(打破单一责任原则)
  • A view is tightly coupled to HTML. 视图与HTML紧密耦合。 Because of this, you cannot re-use the same view for another stuff, like XML, JSON. 因此,您不能将相同的视图重用于其他内容,例如XML,JSON。
  • If you do require "views/" . $file . ".php"; 如果你确实require "views/" . $file . ".php"; require "views/" . $file . ".php"; in render() method - you again tighly couple it. render()方法中 - 你再次强烈地结合它。 What if you change the location of views? 如果您更改视图的位置怎么办? Then you would have to slightly rewrite your method. 然后你必须稍微重写你的方法。 This approach merely kills reuse-ability. 这种方法仅仅会杀死重用能力。

To refresh your basic knowledge: 刷新您的基本知识:

Controller (also known as Editor) 控制器(也称为编辑器)

Serves only singular purpose. 仅用于单一目的。 It changes model state - that is, it should take an input that comes from $_POST , $_GET , $_FILES , $_COOKIE . 它改变了模型状态 - 也就是说,它应该接受来自$_POST$_GET$_FILES$_COOKIE In controller only variable assignment should be done and nothing more . 在控制器中,只应进行变量赋值, 仅此而已

class Controller
{
   public function indexAction()
   {
        $this->view->setVar('age', $this->request->getPostParam('age'));
        $this->view->setVar('user', $this->request->getPostParam('user'));
        //...
   }
}

View 视图

A view has a direct access to a model. 视图可以直接访问模型。 In order to make make views more re-usable and maintainable you'd better pass required things as function parameters (or via setters) 为了使make视图更易于重用和维护,你最好将所需的东西作为函数参数(或通过setter)传递

class View
{
   public function render($templateFile, array $vars = array())
   {
      ob_start();
      extract($vars);
      require($templateFile);

      return ob_get_clean();
   }
}

How the view should be initialized and how the variables should be passed to it? 应该如何初始化视图以及如何将变量传递给它?

First of all - a view should be instantiated outside MVC-triad. 首先 - 视图应该在MVC-triad之外实例化。 Since a controller writes either to view or model - you'd pass variables to view via controller. 由于控制器写入视图或模型 - 您将通过控制器传递变量。

$model = new Model();
$view = new View($model);

$controller = new Controller($view);

// This will assign variables to view
$controller->indexAction();

echo $view->render();

Note : In real world scenario, a model isn't a class, but abstraction layer. 注意:在现实世界中,模型不是类,而是抽象层。 I call it Model for demonstration purposes. 我称之为Model用于演示目的。

IMO the render() method belongs to the view and not to the controller. IMO render()方法属于视图而不属于控制器。 The code should look like this: 代码应该如下所示:

Controller: 控制器:

class SomeController extends AppController
{
    function someaction()
    {   
        $d['text'] = "ahoy!";
        $view = new SomeActionView();
        $view->assign('data', $d);
        echo $view->render();
    }
}

View Base Class: 查看基类:

class View
{

    protected $data;

    function render($template) {
        ob_start();
        // you can access $this->data in template
        require "views/" . $template . ".php";
        $str = ob_get_contents();
        ob_end_clean();
        return $str;
    }


    function assign($key, $val) {
        $this->data[$key] = $val;
    }
}

Extend View class 扩展View类

class SomeActionView extends View
{

    public function render($template = 'someActionTemplate') {
        return parent::render($template);
    }

}

Is this a correct implementation? 这是正确的实施吗? Are there any fallacies with this implementation? 这种实现有什么谬误吗?

Short answer: no and several. 简短的回答:没有和几个。

First of all, what you have there is no a view. 首先,你所拥有的不是一个观点。 It's just a dumb php template . 这只是一个愚蠢的PHP模板 Views in MVC are instance, that contain the UI logic for the application. MVC中的视图是实例,包含应用程序的UI逻辑。 They pull information from model layer and, based on information they receive, create a response. 他们从模型层提取信息,并根据收到的信息创建响应。 This response can be simple text, JSON document, a HTML page assembled from multiple templates or simply a HTTP header. 此响应可以是简单文本,JSON文档,从多个模板组装的HTML页面,也可以是HTTP标头。

As for controller, it's only task is to alter the state of model layer and (on rare occasions) the current view. 至于控制器,它的唯一任务是改变模型层的状态和(在极少数情况下)当前视图。 Controllers do not initialize the views nor do the populate templates. 控制器初始化视图也不填充模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM