Laravel – 5.1 – Middleware For Input Validation
Actually this article is about form validation using a single middleware
. Well, Laravel
peovided us many ways for validating our user inputs and my favorite way is using Form Request
class which is just awesome. Chexk it here if you are not already aware of that. Using a form request class we can validate the incoming request before the coresponding controller method’s code gets executed and to implement this we need to make/create form request class for each controller as per method basis and we declare only one method in that form request class which is the rules()
to declare validation rules for validating the incoming request.
Well, nothing bad in it but I just want to keep my validation rules inside my model and also want to use only a single class for validating all of my models. So, to achieve this, I’ve replaced the form request class using a single middleware and here is how I did it.
At first let’s create the middleware:
namespace App\Http\Middleware; use Closure; use Illuminate\Http\JsonResponse; class InputValidator { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next, $fullyQualifiedNameOfModel) { $model = app($fullyQualifiedNameOfModel); $validator = app('validator')->make($request->input(), $model->rules($request)); if ($validator->fails()) { return $this->response($request, $validator->errors()); } return $next($request); } protected function response($request, $errors) { if($request->ajax()) { return new JsonResponse($errors, 422); } return redirect()->back()->withErrors($errors)->withInput(); } }
Now, we need to add this middleware
in the $routeMiddleware
array in the App\Http\Kernel.php
class, for example, the $routeMiddleware
is given below:
/** * The application's route middleware. * * @var array */ protected $routeMiddleware = [ 'auth' => 'App\Http\Middleware\Authenticate', 'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth', 'guest' => 'App\Http\Middleware\RedirectIfAuthenticated', 'acl' => 'App\Http\Middleware\CheckPermission', 'validator' => 'App\Http\Middleware\InputValidator', // <-- This One ];
Now, to use this middleware
as form validator for our every model we may use this middleware
in the route declaration as given below:
$router->get('create', [ 'uses' => 'TagController@create', 'as' => 'admin.tag.create', 'permission' => 'manage_tag', 'middleware' => 'validator:App\Eloquent\Tag' // Pass the model name (including namespace) ]);
Here, the Validator
is the middleware (alias of original middleware (App\Http\Middleware\InputValidator) class) and the parameter passed into the middleware is App\Eloquent\Tag
to tell the middleware which model to use to get the validation rules so let's create the model with rules()
method, for example, my models are saved in app/Eloquent
directory and namespace
is App\Eloquent
so fully qualified name of the model class was passed as the middleware parameter so we can obtain an instance of that model easily.Let's check out the model now:
'required|unique:tags,tag_title,'.$request->route()->parameter('id'), 'tag_slug' => 'required|unique:tags,tag_slug,'.$request->route()->parameter('id'), ]; } }
That's it. Now, I can validate the request inputs (Submitted Form Inputs) using the middleware and this way I can keep my validation rules inside the model it self and most importantly I can now use only this single middleware to validate all of my models instead of using an individual FormRequest
class for each model. This way still my validation service is out of my controller which runs before the controller method gets called and everything goes very well. That's it.