Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

lara30453's avatar

Laravel 5 and AJAX

I am trying to use ajax in my application. I want the user to be able to see if their email and username is unique and can be used. I used AJAX to give live feedback to the user but I am now getting weird errors when posting via AJAX. Th e errors occurred when I added two fields to be validated: email and username, however, when the email post request is sent with the email and it passes validation it returns the username errors with the email request.

Route::get('/', [

    'uses' => '\App\Http\Controllers\HomeController@index',
    'as' => 'home',
]);

/**
 * Authentication
 */

Route::get('/signup', [

    'uses' => '\App\Http\Controllers\AuthController@getSignup',
    'as' => 'auth.signup',
]);

Route::post('/signup', [

    'uses' => '\App\Http\Controllers\AuthController@postSignup',
]);
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

/**
* 
*/
class AuthController extends Controller {
    
    public function getSignup() {

        return view('auth.signup');
    }

    public function postSignup(Request $request) {

        if($request->ajax()) {

            $this->validate($request, [

                'email' => 'required|unique:users|email|max:254',
                'username' => 'required|unique:users|alpha_dash|max:16',
            ]);
        }

        $this->validate($request, [
            'fullname' => 'required|alpha|max:20',
            'email' => 'required|unique:users|email|max:254',
            'password' => 'required|min:8',
            'username' => 'required|unique:users|alpha_dash|max:16',
        ]);
    }
}
$(function() {

    function getEmail() {

        $.post(
            'signup',
            {
                email: $('#j-email').val(),
                _token: $('input[name="_token"]').val(),
            }
        ).always(function(data) {

            var error = data.responseJSON;

            if(error) {

                $('.error-list').html('<li class="error">' + error.email[0] + '</li>');
                $('#j-email').parent().removeClass('pass');
                $('#j-email').parent().addClass('fail');
                $('.error-list').addClass('show-error');
            } else {

                $('#j-email').parent().removeClass('fail');
                $('#j-email').parent().addClass('pass');
                $('.error-list').removeClass('show-error');
            }
        });
    }

    function getUsername() {

        $.post(
            'signup',
            {
                username: $('#j-username').val(),
                _token: $('input[name="_token"]').val(),
            }
        ).always(function(data) {

            var error = data.responseJSON;

            if(error) {

                $('.error-list').html('<li class="error">' + error.username[0] + '</li>');
                $('#j-username').parent().removeClass('pass');
                $('#j-username').parent().addClass('fail');
                $('.error-list').addClass('show-error');
            } else {

                $('#j-username').parent().removeClass('fail');
                $('#j-username').parent().addClass('pass');
                $('.error-list').removeClass('show-error');
            }
        });
    }



    $('#j-email').on('blur', function() {

        getEmail();
    });

    $('#j-username').on('blur', function() {

        getUsername();
    });
});

So, do i have to create separate controllers for these ajax post requests ? Can I separate the validation into two if blocks that detect what input has been sent ? I'm not sure, but when the validation passes it returns all errors that should only be called when the form is all posted not via a single ajax post.

0 likes
19 replies
XSkinner's avatar

I think it is because you have required for both fields when checking via ajax...

lara30453's avatar

@XSkinner I tried your solution by removing required off the email and username, however, now it does not even validate these two fields via ajax, instead it skips the if ajax block and runs the validation block with full name ect fields in it and returns it to me from my ajax post request that posted the email ???

Th response

{"fullname":["The fullname field is required."],"email":["The email field is required."],"password":["The password field is required."],"username":["The username field is required."]}

XSkinner's avatar

Try setting the complete if statement if (ajax) { username and email check } else { all fields check, even username and email with required }

lara30453's avatar

@XSkinner I tried this method, yet agin with no breakthrough! Should I just use specific routes for the ajax requests to break it up from the post logic, and use different routes ? Like this -

Route::post('/signup', [

    'uses' => '\App\Http\Controllers\AuthController@postSignup',
]);

Route::post('/signup/ajaxGetEmailSignup', [

    'uses' => '\App\Http\Controllers\AuthController@ajaxGetEmailSignup',
]);

Route::post('/signup/ajaxGetUsernameSignup', [

    'uses' => '\App\Http\Controllers\AuthController@ajaxGetUsernameSignup',
]);
    public function postSignup(Request $request) {

        dd('Posted');
    }

    public function ajaxGetEmailSignup(Request $request) {

        if($request->ajax()) {

            $this->validate($request, [

                'email' => 'required|unique:users|email|max:254',
            ]);

            return response()->json(['success' => 'passed'], 200);
        }
    }

    public function ajaxGetUsernameSignup(Request $request) {

        if($request->ajax()) {

            $this->validate($request, [

                'username' => 'required|unique:users|alpha_dash|max:15',
            ]);

            return response()->json(['success' => 'passed'], 200);
        }
    }

However, this seems messy and will have an effect on performance ? Not DRY ? Or can I use this ?

jlrdw's avatar

Have you searched Ajax on the forum, there are tons of previous post to learn from. I have even posted code and a video to prove that the code works before.

jlrdw's avatar

First of all email will be unique second do a simple search for the username they choose if it's already in the database simply have a pop up let them know that they need to choose a different username. Try to keep it simple. https://jqueryui.com/dialog/

prithvi's avatar

You should use different routes for email and username verification.

lara30453's avatar

@jlrdw I have searched all over the place for ajax with laravel 5, but it lacks documentation and any tuts that are explained well.

@prithvi I included an example of me using different routes with different functions within my auth controller, is this an ok method to do this?

Snapey's avatar

You can do this quite easily without using the validator, but if you want to do it that way then you should probably use a try..catch block so that you can return a suitable message to the javascript.

You also don't need that ajax check.

I have a similar function like this, where the user has to think of a slug that is not already taken;

public function slugCheck($slug){

        $slug = strtolower($slug);

        // is the slug in the banned words list
        // cannot choose a slug that is reserved for other routes
        if(array_search($slug, array('pages','ajax','auth','organiser','dashboard','campaign','admin','password','contact'))){
            return array('status' => 'nok', 'message' => 'This slug is on a list of reserved names');
        }

        if(Campaign::where('slug','=',$slug)->first()) {
            return array('status' => 'nok', 'message' => 'This slug is already taken');
        } else {
            return array('status' => 'ok', 'message' => 'Slug is unique');
        }

    } 

and then in the javascript

//for checking for a unique slug
$(document).ready(function(){

    $('#slug').keyup(function(){

        self=$(this);

        var theSlug=self.val();

        //check for, and override banned characters
        theSlug = theSlug.replace(/\//gi, "-");
        theSlug = theSlug.replace(/\ /gi, "-");
        theSlug = theSlug.replace(/\\/gi, "-");
        theSlug = theSlug.replace(/\?/gi, "-");

        self.val(theSlug);

        if(theSlug.length > 8){

            slugcheck(theSlug);

        } else {
            $('#slugGroup').addClass('has-feedback has-warning')
            .removeClass('has-success')
            .removeClass('has-error');
            $('#slugMessage').html('<i class="fa fa-exclamation-triangle"></i>The slug is too short');
            $('#slugPreview').text('...');

        }
    });

    //perform a check on the server to see if this slug exists

    function slugcheck(theSlug){

        $.ajax({
            type: "GET",
            url: "/ajax/slugcheck/" + theSlug,
            })
            .done(function(msg) {
                if(msg['status']=='ok'){
                    $('#slugGroup').addClass('has-feedback has-success')
                    .removeClass('has-error')
                    .removeClass('has-warning');
                    $('#slugMessage').html('<i class="fa fa-check"></i>' + msg['message']);
                    $('#slugPreview').text(theSlug);

                } else {
                    $('#slugGroup').addClass('has-feedback has-error')
                    .removeClass('has-success')
                    .removeClass('has-warning');
                    $('#slugMessage').html('<i class="fa fa-ban"></i>' + msg['message']);
                    $('#slugPreview').text('...');
                }
            

        });
    }

});

lara30453's avatar

I honestly think their is some sort of bug in laravel! I have looked around and re-designed the code in manny differnt ways to get this to work, but it doesnt. This is the final code I have wrote and still it does not work:

JS/AJAX:

$(function() {

    function getEmail() {

        $.post(
            'signup',
            {
                email: $('#j-email').val(),
                _token: $('input[name="_token"]').val(),
            }
        ).done(function(data) {

            var data = data.responseJSON;

            if(data) {

                $('.error-list').html('<li class="error">' + data.email[0] + '</li>');
                $('#j-email').parent().removeClass('pass');
                $('#j-email').parent().addClass('fail');
                $('.error-list').addClass('show-error');
            } else {

                $('#j-email').parent().removeClass('fail');
                $('#j-email').parent().addClass('pass');
                $('.error-list').removeClass('show-error');
            }
        });
    }

    function getUsername() {
        
        $.post(
            'signup',
            {
                username: $('#j-username').val(),
                _token: $('input[name="_token"]').val(),
            }
        ).done(function(data) {

            var data = data.responseJSON;

            if(data) {

                $('.error-list').html('<li class="error">' + data.email[0] + '</li>');
                $('#j-username').parent().removeClass('pass');
                $('#j-username').parent().addClass('fail');
                $('.error-list').addClass('show-error');
            } else {

                $('#j-username').parent().removeClass('fail');
                $('#j-username').parent().addClass('pass');
                $('.error-list').removeClass('show-error');
            }
        });
    }
        
    $('form').on('submit', function(event) {

        if($('#j-email').parent().hasClass('fail')) {

            event.preventDefault();
            getEmail();
        } else if($('#j-username').parent().hasClass('fail')) {

            event.preventDefault();
            getUsername();
        }
    });

    $('#j-email').on('blur', function() {

        getEmail();
    });

    $('#j-username').on('blur', function() {

        getUsername();
    });
});

Routes:

Route::get('/', [

    'uses' => '\App\Http\Controllers\HomeController@index',
    'as' => 'home',
]);

/**
 * Authentication
 */

Route::get('/signup', [

    'uses' => '\App\Http\Controllers\AuthController@getSignup',
    'as' => 'auth.signup',
]);

Route::post('/signup', [

    'uses' => '\App\Http\Controllers\AuthController@postSignup',
]);

Controller:

namespace App\Http\Controllers;

use Validator;
use Illuminate\Http\Request;

/**
* 
*/
class AuthController extends Controller {
    
    public function getSignup() {

        return view('auth.signup');
    }

    public function postSignup(Request $request) {

        if($request->ajax()) {

            $validator = Validator::make($request->all(), [

                'email' => 'required|unique:users|email|max:255',
                'username' => 'required|unique:users|alpha_num|min:2|max:20',
            ]);

            if($validator->fails()) {

                return $validator->messages();
            }
        }
    }
}

If any of you guys want to stick this code in a dummy app to see the problem that please do have a look. Just to re-iterate the problem - When the post request is sent, it comes back saying that they are required, however, they are required but it keeps on returning that error. When I remove the required validation from the validator it does not work anymore!

Should I just use independant routes for both the email and username check, with separate functions in the auth controller - it works that way, but doesn't seem secure!

lara30453's avatar

Note - It also works if I remove either the validation for email or username. I suppose this works because it can not return 'The username is required' if the email is the only validation rule.

Snapey's avatar

but you have two separate ajax calls. when checking the email, you are missing the username and vice versa

Plus you have nothing returned from the calls so really, i'm not sure what you are trying to achieve.

lara30453's avatar

I have two ajax calls: one for email and the other for username? And I'm trying to achieve live validation on these two fields. All I want to do is return the error associated with that input sent to the php, however, it keeps on saying that they are required when there is data sent! And I don't want to validate both fields simultaneously, I only want the field to be validated that the user is entering data into.

lara30453's avatar

Figured it out! Had to split up validation into if blocks to catch input for that validation. Your thoughts on it? How can I make it better? Will tis affect my performance ?

    public function postSignup(Request $request) {

        if($request->ajax()) {

            if(isset($_POST['email'])) {

                $validator = Validator::make($request->all(), [

                    'email' => 'required|unique:users|email|max:255',
                ]);
            }

            if(isset($_POST['username'])) {

                $validator = Validator::make($request->all(), [

                    'username' => 'required|unique:users|alpha_num|min:3|max:15',
                ]);
            }

            if($validator->fails()) {

                return $validator->messages()->first();
            } else {

                return 'passed';
            }
        }

        return 'http';
    }
Snapey's avatar

why make it so hard?

Have one route for check email and one route for check username

Dedicate this code to the ajax call and get rid of the outer ajax check

    public function checkUsername(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'username' => 'required|unique:users|alpha_num|min:3|max:15',
         ]);
         
         if($validator->fails()) {
              return $validator->messages()->first();
         } else {
             return 'passed';
          }
    }

repeat same for email

1 like
lara30453's avatar

@Snapey Ok, so I made two dedicated post routes for the ajax, but how do I make it so the user cant navigate to this url, because when I do it throws a laravel error ? And a big thank you for your help throughout this!

prithvi's avatar

@joshgallagher24 : You can do separate ajax calls to separate routes, and validate them in separate methods in the controller.

.post('/signup/email') // for validating email
.post('/signup/username') // for validating username

Map the appropriate routes.

Then in your controller

public function postValidateEmail($request) 
{
   // validate your email here
}
public function postValidateUsername($request) 
{
   // validate your username here
}

Keep your postSignup method simple. Give it a try.

UPDATE: I didn't see, but @Snapey recommended the same.

Please or to participate in this conversation.