将数据从MVC Controller传递到PHP中的View

时间:2022-12-22 11:28:08

I have my own hand-rolled PHP MVC framework for some projects that I'm working on. When I first created the framework, it was in the context of building an admin CMS. Therefore, there was a very nice one-to-one relationship between model, view, and controller. You have a single row in the DB, which maps to a single model. The controller loads the model and passes it to the view to be rendered (such as into an edit form). Nice, clean, and easy.

对于我正在研究的一些项目,我有自己的手动PHP MVC框架。当我第一次创建框架时,它是在构建管理CMS的上下文中。因此,模型,视图和控制器之间存在非常好的一对一关系。数据库中有一行,它映射到单个模型。控制器加载模型并将其传递给要渲染的视图(例如进入编辑表单)。很好,干净,容易。

However, now that I'm working on the front end of the site, things are getting sticky. A page isn't always a view of a single model. It might be a user directory listing with 20 users (each a User model). Furthermore, there might be metadata about the request, such as pagination (current page, total pages, number of results) and/or a search query.

但是,现在我正在网站的前端工作,事情变得越来越棘手。页面并不总是单个模型的视图。它可能是一个包含20个用户的用户目录(每个用户模型)。此外,可能存在关于请求的元数据,例如分页(当前页面,总页数,结果数量)和/或搜索查询。

My question is, what is the cleanest way to pass all this data to the view?

我的问题是,将所有这些数据传递给视图的最简洁方法是什么?

Some options I'm considering:

我正在考虑的一些选择:

  • Have the controller create an array and pass that to the view as a single parameter:

    让控制器创建一个数组并将其作为单个参数传递给视图:

    class UserController{
    
        public function renderView(){
    
            // assume there's some logic to create models, get pagination, etc.
            $data = array()
            $data['models'] = $models; 
            $data['currentPage'] = $current;
            $data['totalPages'] = $total;
            return $view->render($data);
        }
    }
    
    class UserView{
        public function render($data){
            // render the data
        }
    }
    
  • Create properties in the view class and have the controller populate them:

    在视图类中创建属性并让控制器填充它们:

    class UserView{
        public $models;
        public $currentPage;
        public $totalPages;
    }
    
    class UserController{
    
        public function renderView(){
    
            // assume there's some logic to create models, get pagination, etc.
            $view = new UserView();
            $view->models = $models; 
            $view->currentPage = $current;
            $view->totalPages = $total;
            return $view->render();
        }
    }
    
  • Give the view some sort of generic HashMap or Collection object as a container which can hold any arbitrary number and name of data.

    为视图提供某种通用HashMap或Collection对象作为容器,可以容纳任意数量和数据名称。

    class UserView{
        public $collection = new Collection(); // works like a Java collection
    }
    
    class UserController{
    
        public function renderView(){
    
            // assume there's some logic to create models, get pagination, etc. 
            $view = new UserView();
            $view->collection->add($models,'models');
            $view->collection->add($currentPage,'currentPage');        
            return $view->render();
        }
    }
    

I know that technically any of the could work, but I'm unsure of the best choice, or if there's a better or more conventional choice that I'm missing.

我知道技术上任何一个都可以工作,但我不确定最佳选择,或者是否有一个更好或更传统的选择,我错过了。

3 个解决方案

#1


3  

I'm going to recommend the concept of Fat Models, Skinny Controllers (or, Fat Models Thin Controllers if you prefer...)

我将推荐Fat Models,Skinny Controllers(或Fat Models Thin Controllers,如果您愿意......)的概念

In otherwords, your model is too strict - tying your model to represent only something like a RowDataGateway is extremely limiting.

换句话说,你的模型太严格了 - 将你的模型绑定到仅代表RowDataGateway这样的东西是非常有限的。

In fact, I think good models hide the fact that you're reading the data from a database at all. Because, in reality, your data could be in text files, or from a web service, or whatever. If you treat your Model like nothing more than a glorified DBAL, you doom yourself to having tightly-coupled code in your controllers that just won't let you break away from the "data only comes from the database" way of thinking.

事实上,我认为好的模型隐藏了你从数据库中读取数据的事实。实际上,因为您的数据可能位于文本文件中,也可能来自Web服务或其他任何内容。如果你认为你的模型只不过是一个美化的DBAL,那么你自己就会在控制器中使用紧密耦合的代码,这样就不会让你脱离“数据只来自数据库”的思维方式。

#2


0  

I've seen both of the first two methods implemented in popular MVC/templating frameworks.

我已经看到了流行的MVC /模板框架中实现的前两种方法。

django uses the first method, passing to the view a dictionary of variables which the view uses to fill the template.

django使用第一种方法,将视图用来填充模板的变量字典传递给视图。

smarty uses the second method, creating a Smarty object and assigning values to each the properties in the container.

smarty使用第二种方法,创建Smarty对象并为容器中的每个属性分配值。

Your third method seems to essentially be the same as the second, with minor architecture differences.

您的第三种方法似乎与第二种方法基本相同,但架构方面存在细微差别。

Really, I guess I haven't said anything that you haven't thought of already. Basically, these are all sounds ideas, so implement whatever you feel you are most comfortable with.

真的,我想我还没有说过你没想过的任何事情。基本上,这些都是听起来的想法,所以要实现你觉得最舒服的任何东西。

#3


0  

In the one I use, it has automatically has a view property in the controller that you can access methods and properties on the view. All public properties are then accessible within the view view '$this' since the view is rendered in it's own objects context.

在我使用的那个中,它在控制器中自动拥有一个view属性,您可以访问视图上的方法和属性。然后可以在视图视图'$ this'中访问所有公共属性,因为视图在其自己的对象上下文中呈现。

In the controller:

在控制器中:

$this->view->myVar = 'test';

And in the view:

在视图中:

$this->myVar; // 'test'

The same goes for the layout since the are both separate instances of the same view object:

布局也是如此,因为它们都是同一视图对象的独立实例:

$this->layout->myVar = 'test';

And then in the layout:

然后在布局中:

$this->myVar; // 'test'

The framework used to be proprietary, but is about to be released to the general public. I'd be happy to send you some code from it if you think that'd help. Remember, the simplest answer is usually the best answer.

该框架过去是专有的,但即将发布给公众。如果您认为有帮助,我很乐意向您发送一些代码。请记住,最简单的答案通常是最好的答案。

#1


3  

I'm going to recommend the concept of Fat Models, Skinny Controllers (or, Fat Models Thin Controllers if you prefer...)

我将推荐Fat Models,Skinny Controllers(或Fat Models Thin Controllers,如果您愿意......)的概念

In otherwords, your model is too strict - tying your model to represent only something like a RowDataGateway is extremely limiting.

换句话说,你的模型太严格了 - 将你的模型绑定到仅代表RowDataGateway这样的东西是非常有限的。

In fact, I think good models hide the fact that you're reading the data from a database at all. Because, in reality, your data could be in text files, or from a web service, or whatever. If you treat your Model like nothing more than a glorified DBAL, you doom yourself to having tightly-coupled code in your controllers that just won't let you break away from the "data only comes from the database" way of thinking.

事实上,我认为好的模型隐藏了你从数据库中读取数据的事实。实际上,因为您的数据可能位于文本文件中,也可能来自Web服务或其他任何内容。如果你认为你的模型只不过是一个美化的DBAL,那么你自己就会在控制器中使用紧密耦合的代码,这样就不会让你脱离“数据只来自数据库”的思维方式。

#2


0  

I've seen both of the first two methods implemented in popular MVC/templating frameworks.

我已经看到了流行的MVC /模板框架中实现的前两种方法。

django uses the first method, passing to the view a dictionary of variables which the view uses to fill the template.

django使用第一种方法,将视图用来填充模板的变量字典传递给视图。

smarty uses the second method, creating a Smarty object and assigning values to each the properties in the container.

smarty使用第二种方法,创建Smarty对象并为容器中的每个属性分配值。

Your third method seems to essentially be the same as the second, with minor architecture differences.

您的第三种方法似乎与第二种方法基本相同,但架构方面存在细微差别。

Really, I guess I haven't said anything that you haven't thought of already. Basically, these are all sounds ideas, so implement whatever you feel you are most comfortable with.

真的,我想我还没有说过你没想过的任何事情。基本上,这些都是听起来的想法,所以要实现你觉得最舒服的任何东西。

#3


0  

In the one I use, it has automatically has a view property in the controller that you can access methods and properties on the view. All public properties are then accessible within the view view '$this' since the view is rendered in it's own objects context.

在我使用的那个中,它在控制器中自动拥有一个view属性,您可以访问视图上的方法和属性。然后可以在视图视图'$ this'中访问所有公共属性,因为视图在其自己的对象上下文中呈现。

In the controller:

在控制器中:

$this->view->myVar = 'test';

And in the view:

在视图中:

$this->myVar; // 'test'

The same goes for the layout since the are both separate instances of the same view object:

布局也是如此,因为它们都是同一视图对象的独立实例:

$this->layout->myVar = 'test';

And then in the layout:

然后在布局中:

$this->myVar; // 'test'

The framework used to be proprietary, but is about to be released to the general public. I'd be happy to send you some code from it if you think that'd help. Remember, the simplest answer is usually the best answer.

该框架过去是专有的,但即将发布给公众。如果您认为有帮助,我很乐意向您发送一些代码。请记住,最简单的答案通常是最好的答案。