PHP Laravel Form Validation with Tips and Tricks

Laravel provides various methods for validating the user-submitted form. These methods are very easy and can be learnt by those who are new to laravel.
In this post, you will learn from the validation of fields, nested fields and files.

Simple Form Validation

Let us taken an example of simple contact form submission which contains first_name, last_name, email, phone and subject are mandatory fields and message is an optional field.

In laravel_queues/routes/web.php create below routes.

Route::get('contact-us', 'HomeController@contactUs');
Route::post('contact-us/send', 'HomeController@sendContactUsMessage');

Route contact-us which is a GET method will display form and contact-us/send which is a POST method will validate the form.

In laravel_queues/app/Http/Controllers/HomeController.php. You have to specify two methods they are contactUs and sendContactUsMessage.

public function contactUs(Request $request){
    return view('form-validation.contact-us', []);
}

public function sendContactUsMessage(Request $request){
    $validated_data = $request->validate([
        'first_name' => 'required|max:255',
        'last_name' => 'required',
        'email' => 'required|email',
        'phone' => 'required|numeric',
        'subject' => 'required',
    ]); 

    dd($validated_data);
}

To validate post data an array must be passed into the method validate() and the array key consists of field name and array value has rules which will be applied to that particular field.

You can specify multiple rules separated by |. And if any field fails validation than it is redirected back to the form.

In laravel_queues/resources/views/form-validation/contact-us.blade.php. We have created a form using HTML tags and when the form is submitted the data is sent to route contact-us/send.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Contact Us</title>
    </head>
    <body>

        @if(!empty($errors->all()))
            <h2>Validation errors while filling form.</h2>
            <ul style="color: red" >
                @foreach($errors->all() as $k => $v)
                    <li>{{ $v }}</li>
                @endforeach
            </ul>
        @endif


        <h2>Contact us Form</h2>

        <form action="{{ url('contact-us/send') }}" method="post">
            @csrf
            <label for="first_name">First Name</label><br>
            <input type="text" name="first_name" value="">
            <br><br>

            <label for="last_name">Last Name</label><br>
            <input type="text" name="last_name" value="">
            <br><br>

            <label for="email">Email</label><br>
            <input type="text" name="email" value="">
            <br><br>

            <label for="phone">phone</label><br>
            <input type="text" name="phone" value="">
            <br><br>
            
            <label for="subject">Subject</label><br>
            <input type="text" name="subject" value="">
            <br><br>

            <label for="message">Message</label><br>
            <textarea type="text" name="message" value=""></textarea><br><br>
            
            <input type="submit" value="Submit"><br><br>
        </form>
    </body>
</html>

If the form did not pass validation test than errors as sent back in the object $errors. $errors->all() will return a list of all the objects.
PHP laravel simple contact us form before validation

PHP Laravel simple contact us form after validation of empty form

PHP Laravel simple contact us form validated data

Displaying Validation message in views

Validation error messages are implicitly sent into an object $errors. For looping through all the error messages call the method all() which will return an array.

$errors->all() //contains list of error message

Loop through a list of errors in view.

@foreach($errors->all() as $k => $v)
    {{ $v }}
@endforeach

For displaying message related to particular field use the method first('field_name').

    @if($errors->first('email'))
        {{ $errors->first('email') }}
    @endif

    <label for="email">Email</label><br>
    <input type="text" name="email" value="">
    @if($errors->first('email'))
        <br>
        <label for="" style="color:red;">{{ $errors->first('email') }}</label>
    @endif

You can use IF condition to check if the message for that field exists. You can also use the $errors->has('field_name') method which return TRUE is error message exists.

PHP Laravel display error message of specific field

Nested Field Validation

Nested validations usually occur in complex fields which contains multi-dimensional fields. Here you will find an example of a company profile form which consist of two Point of Contact section where company agent information and contact number must be given.
The condition is that at least one personal information must be given and the two is optional.

In laravel_queues/routes/web.php create below routes.

Route::get('company/profile', 'HomeController@companyProfile'); 
Route::post('company/profile/save', 'HomeController@saveCompanyProfile');

In laravel_queues/app/Http/Controllers/HomeController.php. You have to specify two methods they are companyProfile and saveCompanyProfile.

public function companyProfile(Request $request){
    return view('form-validation.company-profile-form', []);
}

public function saveCompanyProfile(Request $request){
    $validated_data = $request->validate([
        'company_name' => 'required|max:255',
        'company_location' => 'nullable',
        'company_email' => 'required|email',
        'company_point_of_contact.0.name' => 'required',
        'company_point_of_contact.0.phone' => 'required|numeric',
        'company_point_of_contact.0.email' => 'required|email',
    ]);

    dd($validated_data);
}

In laravel_queues/resources/views/form-validation/company-profile-form.blade.php.

<h2>Company Profile</h2>

<form action="{{ url('company/profile/save') }}" method="post">
    @csrf
    <label for="company_name">Company Name</label><br>
    <input type="text" name="company_name" value="">
    @if($errors->first('company_name'))
        <br>
        <label for="" style="color:red;">{{ $errors->first('company_name') }}</label>
    @endif
    <br><br>

    <label for="company_location">Company Location</label><br>
    <input type="text" name="company_location" value="">
    @if($errors->first('company_location'))
        <br>
        <label for="" style="color:red;">{{ $errors->first('company_location') }}</label>
    @endif
    <br><br>

    <label for="company_email">Company Email</label><br>
    <input type="text" name="company_email" value="">
    @if($errors->first('company_email'))
        <br>
        <label for="" style="color:red;">{{ $errors->first('company_email') }}</label>
    @endif
    <br><br>

    <hr>

    <h3>Point Of Contact 1</h3>
    <label for="company_point_of_contact[0][name]">Company Agent Name</label><br>
    <input type="text" name="company_point_of_contact[0][name]" value="">
    @if($errors->first('company_point_of_contact.0.name')) 
        <br>
        <label for="" style="color:red;">{{ $errors->first('company_point_of_contact.0.name') }}</label>
    @endif
    <br><br>

    <label for="company_point_of_contact[0][phone]">Contact Number</label><br>
    <input type="text" name="company_point_of_contact[0][phone]" value="">
    @if($errors->first('company_point_of_contact.0.phone')) 
        <br>
        <label for="" style="color:red;">{{ $errors->first('company_point_of_contact.0.phone') }}</label>
    @endif
    <br><br>

    <label for="company_point_of_contact[0][email]">Contact Email</label><br>
    <input type="text" name="company_point_of_contact[0][email]" value="">
    @if($errors->first('company_point_of_contact.0.email')) 
        <br>
        <label for="" style="color:red;">{{ $errors->first('company_point_of_contact.0.email') }}</label>
    @endif

    <hr>

    <h3>Point Of Contact 2</h3>
    <label for="company_point_of_contact[1][name]">Company Agent Name</label><br>
    <input type="text" name="company_point_of_contact[1][name]" value="">
    <br><br>
    
    <label for="company_point_of_contact[1][phone]">Contact Number</label><br>
    <input type="text" name="company_point_of_contact[1][phone]" value="">
    <br><br>

    <label for="company_point_of_contact[1][email]">Contact Email</label><br>
    <input type="text" name="company_point_of_contact[1][email]" value="">
    
    <br><br>
    
    <input type="submit" value="Submit"><br><br>
</form>

PHP Laravel nested validation before and after form submission

PHP Laravel nested form validated data

File and Image Validation

It is possible for validating a file and multiple files of different mime-types using rules in laravel. Consider a user profile picture upload form where the uploaded file must be an image and must have min dimension.

In laravel_queues/routes/web.php create below routes.

Route::get('user/profile', 'HomeController@userProfileForm');
Route::post('user/profile/save', 'HomeController@saveUserProfileForm');

In laravel_queues/app/Http/Controllers/HomeController.php. You have to specify two methods they are userProfileForm and saveUserProfileForm.

public function userProfileForm(Request $request){
    return view('form-validation.user-profile-form', []);
}

public function saveUserProfileForm(Request $request){
    $validated_data = $request->validate([
        'image' => 'file|image|mimetypes:image/jpeg|dimensions:min_width=100,min_height=100',
    ]);

    dd($validated_data);
}

In laravel_queues/resources/views/form-validation/user-profile-form.blade.php.

<h3>User Profile</h3>
<form action="{{ url('user/profile/save') }}" method="post" enctype="multipart/form-data" >
    @csrf

    <label for="image">Upload Image</label><br>
    <input type="file" name="image" id="">
    @if($errors->first('image')) 
        <br>
        <label for="" style="color:red;">{{ $errors->first('image') }}</label>
    @endif
    <br><br>
    <input type="submit" value="save">
</form>

File validation error message respective to the specified rule:

  • file: The image must be a file.
  • image: The image must be an image.
  • mimetypes: The image must be a file of type: image/jpeg.
  • dimensions: The image has invalid image dimensions.

Define own validators and customize validation message

If you need more customized validator than class Validator is your template through which you can make your own validation and also easily customize them.

Use use Illuminate\Support\Facades\Validator; class to create a custom validator.

$rules=[
    'username' => 'required',
    'password' => 'required',
];
$msg=[
    'username.required' => 'Username is required.',
    'password.required' => 'Password is required.',
];
$validator_object = Validator::make($request->all(),$rules,$msg);

The make(array $validation_list, array $rules, array $message) method takes three arguments array to validate, rule to validate given array and optional message parameter for displaying a custom error message.

To test if all the fields meet validation condition use the method fail() which returns TRUE if errors exist in the form.

$validator_object->fails(); // returns boolean value

Conditional Validation

Suppose have a form were validation must be performed of certain conditions and if those conditions do not match then return back to form with a message. You can make use of the method after() which takes a closure function and inside that function, you can perform custom validations through conditional statements.

Through the method add(string field_name, string error message to display) will add a message to validator error bag.

In laravel_queues/app/Http/Controllers/HomeController.php.

 
$rules=[
    'image' => 'file|image|dimensions:min_width=100,min_height=100',
];
$validator_object = Validator::make($request->all(),$rules);

$validator_object->after(function ($validator) {
    $validator->errors()->add('image', 'Something is wrong with image. check once again and reupload.');
});
dd($validator_object->errors());

PHP Laravel conditional validation of image

In laravel_queues/app/Http/Controllers/HomeController.php.

return redirect('user/profile')
    ->withErrors($validator_object)
    ->withInput();

The method withErrors($validator_object) is used to return that validation message back to views. If you are using make() method to create validators than you must manually send error messages to views.
PHP Laravel conditional validation of image in views

Repopulate form after failing validation

If validation errors occur then the partial form data submitted by a user must be repopulated as this will reduce unnecessary time consumption to again fill those fields. Use the function old() which contains the previous field data submitted by user.

Syntax

old('field_name')

This will return a string which is a data-filled by user for that particular field.

Below is the code using this in HTML form.

<input type="text" name="first_name" value="{{ old('first_name') }}">

Specifying Optional Validation fields

When it comes for validation it is good to practise to specify all the fields which will be submitted through the form. And for fields which are optional than can be left blank use nullable rule.

'field' => 'nullable'

This is just a tip of the ice burg and to know more about validations visit Laravel documentation.

Conclusion

You can come to an end of our article on PHP Laravel Form Validation with Tips and Tricks. For any queries, you can comment below and our developer will address your issue and also don’t forget to share.

Related Posts