How to correctly pass data from controller to view

2020-02-22 07:54发布

My current implementation:

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

And in AppController:

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

And the $data will be available in the views file. Is this a correct implementation? Are there any fallacies with this implementation?

3条回答
Ridiculous、
2楼-- · 2020-02-22 08:28

IMO the render() method belongs to the view and not to the controller. 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

class SomeActionView extends View
{

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

}
查看更多
再贱就再见
3楼-- · 2020-02-22 08:29

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. Views in MVC are instance, that contain the UI logic for the application. 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.

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.

查看更多
劳资没心,怎么记你
4楼-- · 2020-02-22 08:46

And the $data will be available in the views file. 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. Because of this, you cannot re-use the same view for another stuff, like XML, JSON.
  • If you do require "views/" . $file . ".php"; in render() method - you again tighly couple it. 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. 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)

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. 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.

查看更多
登录 后发表回答