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.
— The End —