【问题标题】:Passing data from Controller to View in a PHP MVC app在 PHP MVC 应用程序中将数据从控制器传递到视图
【发布时间】:2013-06-21 04:21:21
【问题描述】:

在几乎所有关于 SO 的教程或答案中,我看到了一种将数据从 Controller 发送到 View 的常用方法,View 类通常看起来与下面的代码类似:

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;
    }
}

我不明白为什么需要将数据放入数组中,然后调用 extract($this->_data)。 为什么不直接将一些属性从控制器像

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

然后在我的布局或模板文件中我可以这样做:

echo $this->title;

【问题讨论】:

    标签: php templates variable-assignment


    【解决方案1】:

    我猜原因可能只是“少打字”,但这有一些很好的副作用:

    • 帮助编写模板的人不熟悉 php,这样他们就不必关心“$this-> 是什么意思?”。
    • 当视图的某些属性应该是该类私有的并且库编写者不想将它们公开给模板编写者时,为变量设置一个单独的容器也很有帮助
    • 防止名称与视图自身的属性和模板变量发生冲突。
    • 比基于方法的访问方案快得多。现在可能不像创建 smarty 时那样相关(也与 php4 一起使用)。

    【讨论】:

    • 同意第 1 点和第 3 点。但是关于你的第二点,我认为容器不允许隐藏 View 的私有属性,你仍然可以这样做 $this->somePrivateProperty 因为文件是从 View 类中包含的(参见上面的代码)。
    • 当然可以,但至少这样看起来与应该访问的“正常”变量截然不同。
    【解决方案2】:

    对视图数据进行分组并将其与内部视图类属性区分开在逻辑上是有意义的。

    PHP 将允许您动态分配属性,因此您只需实例化 View 类并将您的视图数据分配为属性。不过我个人不会推荐这个。如果您想遍历视图数据,或者只是将其转储以进行调试怎么办?

    将视图数据存储在数组中或包含对象并不意味着您必须使用$this->get('x') 来访问它。一个选项是使用 PHP5 的 Property Overloading,它允许您将数据存储为一个数组,而 $this->x 接口与来自模板的数据。

    例子:

    class View
    {
        protected $_data = array();
        ...
        ...
    
        public function __get($name)
        {
            if (array_key_exists($name, $this->_data)) {
                return $this->_data[$name];
            }
        }
    }
    

    如果您尝试访问不存在的属性,将调用__get() 方法。所以你现在可以这样做:

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

    在模板中:

    <title><?php echo $this->title; ?></title>
    

    【讨论】:

    • 非常感谢sn-p,太棒了;)
    猜你喜欢
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    相关资源
    最近更新 更多