Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing data from Controller to View in a PHP MVC app

In almost all tutorials or answers on SO, I see a common way to send data from a Controller to the View, the class View often looks something similar than the code below:

class View
{
    protected $_file;
    protected $_data = array();

    public function __construct($file)
    {
        $this->_file = $file;
    }

    public function set($key, $value)
    {
        $this->_data[$key] = $value;
    }

    public function get($key) 
    {
        return $this->_data[$key];
    }

    public function output()
    {
        if (!file_exists($this->_file))
        {
            throw new Exception("Template " . $this->_file . " doesn't exist.");
        }

        extract($this->_data);
        ob_start();
        include($this->_file);
        $output = ob_get_contents();
        ob_end_clean();
        echo $output;
    }
}

I don't understand why I need to put the data in an array and then call extract($this->_data). Why not just put directly some properties to the view from the controller like

$this->_view->title = 'hello world';

then in my layout or template file I could just do:

echo $this->title;
like image 363
Matthew Avatar asked Jun 24 '13 15:06

Matthew


2 Answers

It makes sense logically to group the view data and differentiate it from the internal view class properties.

PHP will allow you to dynamically assign properties so you could just instantiate the View class and assign your view data as properties. Personally I wouldn't recommend this though. What if you wanted to iterate over the view data, or just simply dump it for debugging?

Storing the view data in an array or containing object dosn't mean that you have to use $this->get('x') to access it. An option is to use PHP5's Property Overloading, which will allow you to store the data as an array, yet have the $this->x interface with the data from the template.

Example:

class View
{
    protected $_data = array();
    ...
    ...

    public function __get($name)
    {
        if (array_key_exists($name, $this->_data)) {
            return $this->_data[$name];
        }
    }
}

The __get() method will be called if you try to access a property that doesn't exist. So you can now do:

$view = new View('home.php');
$view->set('title', 'Stackoverflow');

In the template:

<title><?php echo $this->title; ?></title>
like image 81
MrCode Avatar answered Nov 14 '22 20:11

MrCode


My guess that the reason could be simply "less typing", but that have some nice side effects:

  • Helps when the ones writing the templates are not familiar with php and this way they don't have to be concerned with the "what could this $this-> mean?".
  • Having a separate container for the variables also helps when there are some properties of the view that should be private to that class and the library writers doesn't want to expose them to the template writers
  • Prevents name collisions with the view's own properties and the variables for the templates.
  • Much faster than method based access schemes. Might not be as relevant now as it was when for example smarty was created (worked with php4 too).
like image 1
complex857 Avatar answered Nov 14 '22 19:11

complex857