Bonjour Les Amis! In this tutorial I will explain you how to separate form validation from controllers and keep in requests class, So that your controllers are slim and you don't clutter too much of things in your controller.
Working Laravel project or freshly installed Laravel project.
To create fresh Laravel project use the following command:
composer create-project --prefer-dist laravel/laravel project_name
For the sake of demonstration I will be showing User Registration Page. The form fields may not be exactly same as that I have. But this should give you heads up of how to do it.
Usually you do the following ancient way to validate your form in your class.
Here I am taking as INITIAL CODE so that you can compare with FINAL CODE that we will have in the end of this article. You will be really amazed with it.
public static function store()
{
/** Normal Form Validation */
request()->validate([
'name' => 'required|regex:/^[\pL\s\-]+$/u',
'gender' => 'required|in:male,female,other',
'date_of_birth' => 'required|date_format:Y-m-d',
'country' => 'required|exists:countries,id',
'state' => 'required|exists:states,id',
'city' => 'required|exists:cities,id',
'email' => 'required|email|unique:users,email',
'phone' => 'required|digits:10|starts_with:6,7,8,9|unique:users,phone',
'password' => 'required',
'confirm_password' => 'required|same:password'
]);
try{
/** Create User Code. I usually put it in Model class.
You can directly pass the form request for create,
but I am more of no no person for that
*/
$user = User::create([
'name' => request('name'),
'gender' => request('gender'),
'date_of_birth' => request('date_of_birth'),
'country_id' => request('country'),
'state_id' => request('state'),
'city_id' => request('city'),
'email' => request('email'),
'phone' => request('phone'),
'password' => self::encrypt(request('password')),
]);
if(!$user){
throw new Exception('Oops! Some error while creating user. Try again.');
}
session()->flash('success', 'User Registered Successfully');
return redirect('/auth/login');
} catch(\Exception $e) {
session()->flash('error', $e->getMessage());
return redirect()->back()->withInput();
}
}
As you can see in the above example we have form validation & user data adding to database and other code. The controller is cluttered with shit load of code.
Laravel has a feature to move the form requests to separate request class.
Create a CreateUserRequest
Class, where we can put all this hell lot of validation code. Use the following artisan command to create the form request in Laravel.
php artisan make:request CreateUserRequest
This creates the CreateUserRequest.php
class in app/Http/Requests
folder as shown in the following image
Now lets take the user registration form validation from UserController and add the validation in CreateUserRequest class rules()
method as follows
class CreateUserRequest extends FormRequest
{
public function authorize()
{
/** Make sure to make this true */
return true;
}
public function rules()
{
/** Following is the same validation that you had written in your controller */
return [
'name' => 'required|regex:/^[\pL\s\-]+$/u',
'gender' => 'required|in:male,female,other',
'date_of_birth' => 'required|date_format:Y-m-d',
'country' => 'required|exists:countries,id',
'state' => 'required|exists:states,id',
'city' => 'required|exists:cities,id',
'email' => 'required|email|unique:users,email',
'phone' => 'required|digits:10|starts_with:6,7,8,9|unique:users,phone',
'password' => 'required',
'confirm_password' => 'required|same:password',
];
}
/** You can customise validation messages here */
public function messages()
{
return [
'phone.required' => 'Contact number is required',
'phone.digits' => 'Contact number must be numbers',
'phone.starts_with' => 'Contact number is not valid'
];
}
}
Don't forget to make authorize()
function return true. If you want you can even make auth()
validation and return true if the user has permission or not
public function authorize()
{
/** You can check if the user can perform this
validation request based on his access.
For the sake of simplicity I am returning true here
*/
/** Make sure to make this true */
return true;
}
You can customise your validation messages in messages()
function as shown below
public function messages()
{
return [
'phone.required' => 'Contact number is required',
'phone.digits' => 'Contact number must be numbers',
'phone.starts_with' => 'Contact number is not valid'
];
}
The above CreateUserRequest
won't get called automatically we need to inject in UserController
store
method parameter as follows
use App\Http\Requests\CreateUserRequest;
public function store(CreateUserRequest $request)
{
/** User Registration Code */
}
Now overall your UserController will look like the following:
use App\Http\Requests\CreateUserRequest;
public static function store(CreateUserRequest $request)
{
try{
/** Create User Code. I usually put it in Model class.
You can directly pass the form request for create,
but I am more of no no person for that
*/
$user = User::create([
'name' => request('name'),
'gender' => request('gender'),
'date_of_birth' => request('date_of_birth'),
'country_id' => request('country'),
'state_id' => request('state'),
'city_id' => request('city'),
'email' => request('email'),
'phone' => request('phone'),
'password' => self::encrypt(request('password')),
]);
if(!$user){
throw new Exception('Oops! Some error while creating user. Try again.');
}
session()->flash('success', 'User Registered Successfully');
return redirect('/auth/login');
} catch(\Exception $e) {
session()->flash('error', $e->getMessage());
return redirect()->back()->withInput();
}
}
This is much cleaner. Isn't it?
This is lot of controversial topic ie where to put your business logic. As Taylore Otwell himself said we can put it in Models I usually do it there.
Even we can use the Repository Pattern and segregate lot of code moving to that folder. But in this article lets not argue on that. Let me write another article on the same.
Coming back to our code, once I move the registration code to User Model it will look some what this way
Which I am very much satisfied with
use App\Http\Requests\CreateUserRequest;
public static function store(CreateUserRequest $request)
{
try{
$user = User::register($request->all());
if(!$user){
throw new Exception('Oops! Some error while creating user. Try again.');
}
session()->flash('success', 'User Registered Successfully');
return redirect('/auth/login');
} catch(\Exception $e) {
session()->flash('error', $e->getMessage());
return redirect()->back()->withInput();
}
}
There is lot of stuff to share with you guys. But as we know everything cant be covered in a single stretch. So stay tuned & keep learning. Don't forget to share with your friends.
NGINX Security Best Practices & Optimization
Free SSL Certificate For CPanel
Use Different PHP Versions In Ubuntu / Linux
Upload File From Frontend Server {GuzzleHttp} To REST API Server In PHP {Laravel}
Make Laravel Controllers Slim By Skimming Form Validation Request
Securely Connect Server MYSQL DB From Sequel Pro / MYSQL Workbench
PHP Built-In Web Server & Testing Your Development Project In Mobile Without Any Software
Manipulate HTML Using DOMDocument In PHP
Automate Repeating Tasks In Linux Server With Cronjobs
Install NGINX In Linux / Ubuntu And Managing
Accessors And Mutators In PHP Laravel
Simple Way To Create Resourceful API Controller In Laravel
Free SSL Certificate In cPanel With ZeroSSL & Certbot
Send SMS With Amazon SNS (Simple Notification Service) Using PHP