Attention! This post is older than three years, it may or may not be relevant anymore.

TL;DR

The author faced an issue where Laravel’s in-built Validator class did not work properly while uploading audio files in a form via jQuery ajax. After trying different solutions, the author created a custom validation in Laravel based on the file extension of uploaded files using Validator::extend() method. The article provides a step-by-step guide on how to create a custom validation in Laravel and specify default error messages.

I know what you are thinking. You are thinking what’s even the need of this topic. I mean sure with Laravel’s in-built Validator class, validation at server side has become easier as ever. But, Laravel’s validation class does screw from time to time and then you have to resort to some custom solution, like I did.

You see, you can learn all about Laravel’s validation from the below documentation page of Laravel, explaining the Laravel’s validation class uses:
https://laravel.com/docs/5.3/validation
It’s pretty self explanatory, but there are certain things that you don’t learn in the books.

So, I was working on an application and in that application the user was required to upload audio files in a form via jQuery ajax but the audio files could only be in the mp3 or ogg format as they had to be used in the jPlayer plugin. Now normally the first thing that would come to your mind will be the

validation method, and so I thought of it too. But even after clearly and rightly mentioning the file formats to be allowed, to be only mp3 and ogg, the upload was still giving the error for mp3 validation.

I was working on Laravel 5.2.24 and couldn’t figure out the reason at first since I was new at Laravel 5.x. The first thing that came to my mind was that there might be something wrong with Laravel itself, so I changed the validation as

, and sure enough, it worked all well for that. So, after messing around a bit more I concluded that it was again the time to ask Lord Google for help. To my surprise a lot of people out there were facing the same problem and had some very interesting solution for it.

The first solution that worked for someone else was using

as validation or so I believe. I actually think that the questioner was trying to do something custom by using

or maybe just checking things out. Anyhow, the reason the solution provider gave the questioner was as below:

“The main extension for the audio/mpeg mime type in the Apache list is mpga, not mp3. So if this is the actual logic they use, you need to use mpga to allow the audio/mpeg mime type, not mp3.”

You can check out more about the above case at: Github link
And it’s solution at: Github link

This didn’t work for me, so the hunt continued. There was another post with the same issue, kind of. The questioner however also mentioned that he thought that the reason that Laravel validation as not working because the mime ‘type’ of the upload was not understood by Laravel as ‘audio/mpeg’ but as ‘application/octet-stream’. So I checked this theory out as well since I thought that may be cause I’m uploading via jQuery ajax ‘FormData’ object from Firefox browser, it could be possible, and found that this was not the case for me as well. But for those who also think the same might be happening in their case, the below was the solution or an explanation given for the case:

“Laravel’s getMimeType() builds on top of the native mime_content_type() method, which has trouble detecting certain mp3 files.

Your best bet is to use a custom MIME detector like this one to do the job.”

To read more about the above case, you can visit: Stackoveflow link

Now all this said and done, I couldn’t find any relatable issue and any working solution. So, instead of wasting any more time I focused on looking into how to create a custom validation in Laravel based on file extension of the uploaded files. After going through the Laravel documentaion I found that you can use Validator::extend() method to add some custom rules. You can check out the whole rule from the below link:
Laravel Custom Validation rules

So, here is what I did that worked for me. First I opened the file:
..appProvidersAppServiceProvider.php

And, in the boot method I added the following code:

The ‘mp3_ogg_extension’ in the above code is the name of the validation rule that I may apply in the controller file to the input file name. The second parameter is a function which deals with the validation process. As per the Laravel documentation:

The custom validator Closure receives four arguments: the name of the $attribute being validated, the $value of the attribute, an array of $parameters passed to the rule, and the Validator instance.

You may also pass a class and method to the extend method instead of a Closure:

The ‘$value’ here contains the uploaded file object. Since I was using ajax I checked the object value in the console of firebug. I used the in-built Laravel function getClientOriginalExtension() to check for the uploaded file extensions and then validate them as being mp3 or ogg.

But you are not done yet. You also have to specify the default error message that the user will receive when the validation fails. You can either do this using the custom error message way in Laravel as given at:
Custom Error Messages

that is, as:

or the way I did, like, opening the file:
..resourceslangenvalidation.php
and adding the key and value to the ‘return’ array as:

This is it. Now wherever the validation rule ‘mp3_ogg_extension’ is applied for file uploads it’ll work and validate for the mp3 or ogg files only. Keep in mind that I was uploading via ajax so in my controller all I had to do was convert all the validation error in JSON format and return it in the ajax ‘error’ case and deal it with there. I’m also going to share my jQuery code here and my controller code too as it might help in you better understanding, but if you think it’s making you more confused you can leave right here. Feel free to ask anything you want clarification on

So, here is the code form my jQuery js file:

This might not work as it is if you apply in your code as I have deleted some stuff I think is just junk in the code but might be required for proper functioning.

Noe the code in my controller file:

Now, I’m sure that there are a lot of other ways in which this could’ve been handled and I would love to hear all of them. This was just my take on the issue in the given time.

Are you looking for a reliable custom website development service then check out our services and pricing or contact us and we will get back to you within 24 hours or less.

That’s it. Happy coding 🙂