可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have the common MVC situation in my PHP system: the Controller
receive a request from the View
containing $_POST
data. Now I have three ways to handle the data:
a) The Controller
only calls the Model
and the Model
handle the $_POST
data.
b) The Controller
transforms the $_POST
data into variables and pass them to Model
.
c) The Controller
transforms $_POST
data into a Model
's domain object and only pass the object to Model
.
Currently, I am following option A, but I believe it is wrong, so I am thinking of using option C.
So, according to MVC, what is the right way to handle $_POST
data?
EDIT At the moment, I'm not using any MVC framework.
EDIT 2 Generally, the same Controller
handles request from a browser, a web service, an offline application, etc, or each one has it own Controller
?
回答1:
The best option is to use #2 approach, with some alterations.
I would write it as something like this:
public function postLogin( $request )
{
$service = $this->serviceFactory->build('Recognition');
$service->authenticate( $request->getParam('username'),
$request->getParam('password') );
}
// Yes, that's the whole method
There is no need to actually create variables, if you have used something like a Request
instance to abstract the user's input.
Also, you might want to replace theRequest::getParam()
method with something likeRequest::getPost()
- although I have come to the conclusion that, in a correctly structured application, theGET
andPOST
parameters should not share same name.
The serviceFactory
which you see in the code snippet would be an object that you inject in both controller and view instance. It would let you share same service instances between controllers and views.
It is responsible for creation of services (which would contain the application logic, while leaving the domain business logic in the domain objects), which helps you isolate the interaction between domain entities and storage abstractions from the presentation layer.
About the other options:
The Controller only calls the Model and the Model handle the $_POST data.
In the MVC and MVC-inspired design patterns the model should be aware of neither the user interface nor of the presentation layer as whole. The $_POST
variable in PHP is a superglobal.
If you use it with model layer, your code becomes bound to the web interface and even the specific request method.
The Controller transforms $_POST data into a Model's object and only pass the object to Model
Not entirely sure what you meant with this. Seems you were talking about instantiation of an abstraction, which would contain the user's request. But in this case controller becomes responsible for instantiation/creation of said structure, which would violate SRP.
Closing notes:
One thing you must understand is that, in context of web based MVC applications, the User of your application is the browser. Not you. Browser sends the request, which is handled by routing mechanism and disseminated by controller. And view produces the response to your browser.
And the other thing is: Model is neither a class nor an object. Model is a layer.
Update
Generally, the same Controller handles request from a browser, a web service, an offline application, etc, or each one has it own Controller?
You should be able to have single controller, that deals with all the forms of application. But that is only on the condition, you are actually using same application for all 3 use-cases.
To do so there are two conditions:
- you need to abstract the
Request
instance, that controller receives
- the view should be instantiated outside the controller
This way you can have one application to fulfill all the requirements. Only thing, that each variant has different, is the bootstrap stage, where you create the Request
instance and select the proper view.
In the situation, that you described, the changing part would actually be the view, since a REST or SOAP service would be expected to produce a different response than an ordinary web application.
回答2:
Once upon a time was the three tiered application architecture.
It all depends on your MVC framework. Normally, the Controller does the link between the user and the model layer, which manipulate domain objects.
In the early days of MVC in PHP, the model layer was actually just the domain objects, called models for that purpose.
Some prefered having so called thin models, which only provide an OO representation of the data, (which simplifies persistence). In that case, the controller would regroup the so called actions, containing the bulk of the processing associated with an HTTP request (fat controller).
Others embedded most of said processing in the object model with dedicated methods (fat model).
However, at some point, you have to analyse the content of the query to sanitize and validate it, and this depends on how your view will format the request. Sanitization might be a controller task (this request should only contain these values), while validation is definitely a model task (values should be of these types).
An interesting question is: how do you deal with actions impacting several domain objects? Where do you put the logic for that?
Nowadays, the model layer is composed of services segregating the domain objects from the evil grasp of the controllers, to limit the dependencies between the layers to their respective interfaces only. This is where most of the request processing is done.
Symfony2, for instance, provides a sensible answer to this question: each step of the processing of a request is implemented in a dedicated piece of code, which could be described as the following:
- the request is first turned into an object
- that object is routed using a routing object
- it is handled to a controller
- the controller pass the request to the service concerned by the action, which build the response object
The service job is then broken in several steps:
- validation (using a dedicated object which rely on rules described in a separate file),
- construction/updating of domain objects (using serialization to/from db if necessary),
- selection of a template for the response,
- population of said template with the relevant data from the domains.
CakePHP is another popular framework which follows similar concepts: simple controllers, and services encapsulating domain objects.
See this question for a better insight on the general concepts.
See this other question for other answers.
Thanks to tereško for his invaluable input on the matter.
回答3:
i am using Zend and following
the 2nd option .
Example a Registration form
step- 1 the forms sends me the post value to the specified controller
step -2 i will validate the form values for example ( mail and url and empty post values ) through server side validation .
step -3 send the checked post data either in variable or has whole to the model .
step 4- controller calls the model .
step -5 the models inserts the post values and creates a new user .
I think your second option is better regardless of framework or approah you use .
note - same controller can handle everthing depends on your application logic .
but i prefer to keep different controller for differnt user request and user types
it helps in keeping code readable managebale .
回答4:
Look at some MVC frameworks.
For example, in Yii you can write such code inside action:
$model = new Model();
if(isset($_POST['Model'])) {
$model->attributes = $_POST['Model'];
}
Note, that all attributes
of your model must be passed through validation rules. In Yii validation applies during (actually, before) $model->save()
See:
- http://www.yiiframework.com/doc/guide/1.1/en/form.model#securing-attribute-assignments
- http://www.yiiframework.com/doc/guide/1.1/en/basics.mvc
回答5:
'C' is best option. You should not let raw $POST data go in model as model is supposed to be generic handling store and load operations mainly.
Example : same model can be used web interface and Web services. On Web $_POST is valid but for web services its not. So model doesnt care how data is received but only how to store and load it.
Yii is definitely a clean implementation of MVC.