I'm reimplementing my user management system with Slim, and I'm trying to figure out where I should do user data sanitization/validation. I've been reading about middleware, and I'm wondering if this is an appropriate way to implement data validation.
My plan for validation is to use a validation schema (a simple JSON file) for each request that contains some user data (i.e., forms). However, different forms will obviously use different schema, and there may be some types of validation that cannot be handled by the schema alone.
Thus, any middleware I implement will have to decide which schema to use based on the route. Plus, some routes will require additional validation logic beyond that represented in the schema. This to me sounds like the wrong approach though - isn't middleware supposed to be fairly "generic", performing the same logic on every request/response?
Another approach would be to have some sort of validation object that I initialize in each route with the appropriate schema, and then into which I inject my Slim app.
Which would be the more sensible approach?
Using global middleware doesn't make sense as you end up coupling every endpoint's parameter list together.
The two options I would consider are:
Implement as route middleware so that you can have different filtering/validation for each endpoint.
e.g.
function fooFilter() {
// filter/validate GET variables here and set back into request.
}
$app->get('/foo', 'fooFilter', function () {
// "controller" logic
});
The advantage of doing it this way is that your controller logic doesn't need to be cluttered up with validation stuff as that's already been done.
Filter/validate within the controller logic. The main advantage here is that you can more easily audit if a GET variable is being used without being filtered/validated first.
Related
I am reading the laravel documentation, and there is some doubt about validation
If the web server will provide web interface to desktop user, and api interface to mobile user, there is a problem: It will define validation twice in api controller and web controller, it is duplication.
and if there is a another co-developer to develop a large project, He should to know previous developer defined validation, it is not good for collaborative development
I think It should define validation logic in same place, Like ActiveRecord in Rails
You can create a Request file in the Requests folder and inject this file in controller method and it will automatically validate the request. Please continue reading the Laravel validation documentation here and you will find this method elaborately.
You can add a method to the Models like 'getValidator' which gives you the validator, and then in the controller you just ask this.
However a validator would most of the time want to validate the input from the (user) input. Imagine input that has to be applied to multiple models or complex relationships. It would be strange to say the validation is really part of the/one model. In the end it just validates the input, so you need it in your controller.
A better way of abstracting in your case might be to interpret the 'web' part als also an app, which connects to your API. And then let the API be the only way to interact with your backend, and thus having the validation only in 1 place (the API).
In the end, it's up to you how you structure it.
I come from a Java/Grails background and cannot seem to find a definite answer online as to where the service logic for a CakePHP application should be stored. By "Services", I am talking about classes that are usually instantiated through dependency injection to conduct business logic on domain objects. They should be able to query any domain object and make changes in response to a controller action.
Currently, CakePHP's "Component" class seems to be the closest match to this behavior. I can load a component into any controller and execute its methods as needed. However, I have read in several places that components should never access the database and that doing so will result in some steep performance hits.
I have also looked into CakePHP's "Behavior" class and it doesn't seem to fit the ticket at all. It seems well-equipped to organize domain objects into a data structure setting, but that's not the kind of logic that a service would execute. Also, to import any model definition into a Behavior, I would have to edit the model definition itself to allow access, which is very awkward.
So I ask this question: Where should service logic be stored? Certainly not the controller, as it should only contain the minimal logic to process a request and send a response.
Components are the service layer in CakePHP. They are constructed by a dependency injection container (Components Collection) and get passed the controller, request and response that is to be handled.
There are no restrictions in what Components can do other than maintaining separation between layers. It is fine to use database connections, or use models, directly from a component and modify the request.
Components are actually very light-weighted if you only make them act for specific cases. Inspecting the action name, is a common way of limiting the reach of a component. You can also inject setting so it can know when is OK to execute custom service logic.
So I ask this question: Where should service logic be stored?
Certainly not the controller, as it should only contain the minimal
logic to process a request and send a response.
Sounds like the ideal use case for a Dispatcher Filter. It gets called even before a controller is instantiated. If you need to query the database simply load a model via ClassRegistry::init('YourModelName') and pass the request params to the model method and return whatever you need in your request. No controller needed at all. We've implemented oauth + xhttp using Dispatcher Filters without calling ever a controller.
How using a model inside a component should effect the performance... I don't know who got that strange idea, sounds like not the best article you found. It is true that you should not put model layer related logic in them but you can call a model for example through the controller instance and the controllers models.
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?
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, theGETandPOSTparameters 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.
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.
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 .
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
'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.
I'm just starting to convert some basic applications to CodeIgniter and I'm trying to make sure that I start off on the right footing.
Most actions in my controller require at least 1 query and as I see it there are 2 ways to go about this...
Combine the queries into a single method in the model, therefore making only a single call to the model from the controller.
Have each query be its own method in the model, then call each method in turn from the controller.
So far I've adopted my own policy but I'm not sure if it's advised or breaking the MVC pattern.
If the queries are directly related to one another and only ever run together in sequence (the 2nd query is dependent on the 1st running successful), or data from the 1st query is passed to a 2nd query and it's the 2nd query that returns the actual display result set, then I go with #1
If each of the queries is returning its own individual result set for display, then I go with #2
Is there a recommended way to structure and separate the logic in this scenario?
The last thing I want to do is cause myself a nightmare later down the line. My gut instinct is telling me that as much of the logic should be in the controller as possible.
Your thinking is right in that if a certain set of queries will only ever be run together, they should belong to the same method in the model. Free-standing queries should be in methods of their own, this way you can call them from the controller when required.
To combine multiple queries, you can either make multiple calls from the controller like this:
$this->your_model->doQuery1();
$this->your_model->doQuery2();
$this->your_model->doQuery3();
Or (and this is what I would do), create a wrapper method in the model that runs those three queries.
So you can do
$this->your_model->runQueries();
where
function runQueries() {
$this->doQuery1();
$this->doQuery2();
$this->doQuery3();
}
This makes it more malleable to later change.
Finally, as for your statement 'as much of the logic should be in the controller as possible', this actually goes against the school of though of skinny controller, fat model that some people subscribe to. As any other school of thought, it is not set in stone.
First of all: slapping on a framework on exiting application - always a bad choice. Frameworks do not make you application better. They are there to make development faster.
Also, you have to understand that CodeIgniter is not really implementing proper MVC. Instead it is mimicking Rails architecture and naming conventions. It's actually closer to MVP pattern.
In any case, controllers must be as light as possible.
If implementing proper MVC or MVC-inspired pattern, all of the domain business logic would be in thee model layer and all of presentation logic in the views. Controller would be only passing relevant data to model layer and current view.
When writing code for CodeIgniter, you should keep as much domain logic as possible in the "models" and most of the presentation logic in the view helpers.
What in CodeIgniter are called "models" are mostly domain objects, which sometimes are merged with storage logic (violating SRP) to implement active record pattern.
The best option for you would be to create higher level "models" which would act as services and would separate the controllers from direct interaction with CodeIgniter's "models".
In your described situation, where you have to make two requests to different "models", this operation would be done is the such services. And the service aggregate the data from both "models" and pass it to the controller.
For example: if you are registering new user, you would have to perform two operations - create an entry for the account in storage (usually - database) and sent user notification to email. Those both operations can be contained in the service, that is responsible for user management.
Controller would only ask the service to crate new account. Fact that service would perform multiple operations( initialize a User "model", assign data to it, store it and then on success, initiate Mailer and send an email) is completely irrelevant to the controller. Controller would only want to know the list of errors (if the list was empty, everything was ok).
.. my two cents.
I am working with an MVC framework (specifically, PHP's CodeIgniter). I am trying to follow "best practices" as much as possible, but I don't have much experience with MVC. Is it bad practice for me to retrieve data from a session within the Controller? Should I "ask" the model if, say, a particular session value is 'foo' or 'bar', or should I do that directly inside the Controller? I'm thinking I should do it inside the Model since the session data is technically data, but I just want to make sure. To be clear, I don't store the session data in the database at all, so I'm not running a query.
Models typically handle all domain objects that are persisted to some sort of long-term storage. They may or may not have transient values in them that have to do with the particular application's use of them.
Controllers should be querying any data they need in order to correctly route and display information. It may help to create a 'Service' layer that operates directly on domain objects (your model) and provides an API for Controllers to use. The main thing to not include in Controllers is business logic.
It would be reasonable, for instance, for the Controller to grab the referring page and do something with that data in regards to the user flow. However, apart from validation, it probably shouldn't, say, examine the amount of money being transferred between accounts - it should just pass that on to a service object that instantiates and works with the correct domain objects.
Questions to ask about logic you're putting into a Controller:
Does this logic help figure out what Model objects I need? If not, it shouldn't be here.
Does this logic help figure out what View objects will be used to construct the response to the user? If not, it shouldn't be here.