I'm working with Laravel 5 API. I have a few methods with similar request parameters
For example to check the licence status or get the settings file you need to provide the ?serial=licence_serial_number parameter.
I need to return 400 error code, when the user didn't provide the serial parameter, and 403 error code, when the user is trying to get information about the licence of another user.
What is the best practice to organise validation and error handling of these kind of requests?
Should I make a middleware to check if the user has provided ?serial?
Or should I make a different Laravel 5 FormRequest class for every method?
Or should I validate it directly in a controller with:
if (..) {return response()->json([..], 400);}
$request->wantJson(), with a request with Header Accept=application/json Will tell Laravel to return json validation error instead of goback with errors
Middleware will probably be the best choice but you could also use the Request method.Inline validation is a bad practice as its ignore the most basic rule of programming - Dont Repeat Yourself.
In case you decide go for the request option you aren't supposed to create the authorize method for each class,instead create 1 parent witch will handle this and the other sub classes will just have the rules method.
It depends on a few things acctualy:
If your always validating the same thing for all requests: Go With a Middleware Solution.
But if some or multiple requests validate different things then I would advise on using the new FormRequest from Laravel.
It handles the validation for your request perfectly, and also allows you the define the error responses per request.
Also a middleground is an option, Let middleware validate the thing that needs to be validated always. And FormRequests to handle the variable validation.
If you have similar FormRequests, consider using inheritance to prevent code duplication like a good SOLID programmer :-)
Related
I've looked around but I haven't been able to find a way to perform an existence check of a resource before validating an incoming request with Laravel 8 FormRequest classes.
Basically, I want to perform the following steps when, say, for example, a PUT/PATCH request comes for the update of a resource:
Check if the requested resource exists
Check if the user is authorized to make the update
Validate the fields of the request
Update the resource
Send the response back to the user
From what I've read, it's easy to perform steps 2 and 3 in a FormRequest while 4 and 5 could be done in a Controller (or 4 in a Service and 5 in a Controller).
What I'm missing is how to perform step 1 right at the beginning. I've seen some workarounds like How to throw a 404 in Laravel Form Request with custom Rule maybe alongside How to validate Route Parameters in Laravel 5? but I don't feel that is the proper way to achieve what I'd like to do...
With an existence check in the Controller the user gets to make a valid request first, even though he's trying to update a resource that doesn't exist (as the Framework throws a ValidationException before the Controller method can be invoked) and that doesn't sound right.
Any suggestion on how to "delay" the validation after the existence check could be achieved? Otherwise, should I discard using FormRequests altogether?
Thanks in advance!
What you looking for are database transactions. it will make sure to execute the request only if everything is fine. for more info https://laravel.com/docs/5.8/database#database-transactions
Turns out that this is the default when type-hinting resources to controllers. The existence check comes first, then authorization and only after these comes validation.
Suppose I have a input with type='file'. I want this input to have a validation rule
based on its content. For example, it has specific content structure and if it doesn't, $validator->fails() returns true. I don't want to do that inside controller and make it ugly. What is the best and cleanest approach to do that?
I mean by "cleanest" the best place(directory/class/method) that the logic has should be located.
Thanks
You may wish to create a form requests. Form requests are custom request classes that contain validation logic.
Laravel then automatically passes the user's input into the request before parse through the POST route, meaning our validation can now be moved entirely into FormRequest objects and out of our controllers and models.
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.
We have a CORS REST API. It's clean. It works. It's almost perfect. But...
I'm trying to implement an endpoint with request specific parameters. This endpoint should accept POST, PUT, LINK and DELETE requests. And I'm not sure how to implement these parameters.
An example:
A user wants to DELETE a model. There are two scenario's: one where the model is deleted and nothing else happens, and one where the model is deleted + a notification email is sent out.
Initially I implemented this parameter in a header called "X-NOTIFY-OWNER". This worked since it could be added to any of the 4 actions. But now we'd like to get rid of that header, since it's too specific to this single endpoint.
What whould be the best place to put this parameter? A query parameter sounds cleanest (since DELETE and LINK technically don't need a body), but query parameters should be used to filter content. A parameter in the request body would work too, and seems to be the prefered method; but it means sending a body with the DELETE and LINK actions...
Any thoughts on best practice in this case?
I would stick to a query string, DELETE is supposed to ignore the body and only read the URL so it makes sense to use a query string here.
You should use an URL parameter. As you stated, they should be used to filter output and an e-mail can be considered to be output.
I would recommend setting up a new endpoint for the cleanest solution.
example.com/endpoint
example.com/endpointAndNotify
You could either:
Setup the notify endpoint to extend the base endpoint and then add the notification logic to the notify action.
Abstract out the shared logic from both actions, update each action to extend the base class and then add the specific notification logic to the notify action
This way both endpoints stay clean and concise and if you define a standard for this endpoint, any other endpoints that need notification logic can use the same standard.
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.