9

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;

2 Answers 2

7

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>
Sign up to request clarification or add additional context in comments.

Comments

1

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

2 Comments

Agree for point 1 and point 3. But regarding your second point, I don't think that the container allows to hide the private properties of View, you can still do $this->somePrivateProperty because the file was included from the View class (see code above).
Well of course, but at least this way it would look distinctly apart from the "normal" variables that supposed to be accessed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.