10

I'm using rules in validation in Laravel, and am trying to check the number of characters in a number.

This is my attempt:

protected static $rules = [
    'zip_code' => 'required|size:5|integer'
];

Unfortunately that checks that the zip code is the number 5 and not that the zip code is 5 characters. Which rules do I need to set to check that the zip code is exactly 5 characters, regardless of the actual numbers?

zeckdude
  • 15,877
  • 43
  • 139
  • 187

4 Answers4

19

A zip code is 5 digits long and may contain leading zeros (Northeast US). The Laravel "digits" check drops the leading zeros as a result you need to use a regex pattern:

protected static $rules = [
     'zip_code' => 'required|regex:/\b\d{5}\b/'
];

This will make sure the zip code is always 5 digits long. More details in the Laravel Docs

hurikhan77
  • 5,881
  • 3
  • 32
  • 47
Bogdan
  • 43,166
  • 12
  • 128
  • 129
  • That's exactly what I was looking for! No idea how I missed that. Must have been staring at validation rules for too long. Thanks so much for your help! You the man! – zeckdude Feb 10 '15 at 23:58
  • Do you have any idea where in the code Laravel files these rules are located? I'm curious what php code they used to determine their true/false values that get returned. – zeckdude Feb 11 '15 at 00:00
  • 1
    Yep, they're in `vendor/laravel/framework/src/Illuminate/Validation/Validator.php`. The methods that do the validation begin with `validate`, so for the `digits` rule you'll find `validateDigits`. – Bogdan Feb 11 '15 at 00:02
3

As per Laravel 5.3 :

If you are validating against character field which contains a number and you wanna know if it max 5 or lesser digits then you can use:

protected static $rules = [
    'zip_code' => 'required|max:5|string'
];

If you are validating against integer field and you wanna know if it contains max 5 or lesser digits then use:

protected static $rules = [
    'zip_code' => 'required|max:99999|integer'
];

If you are validating against integer field and you wanna know if it contains exact 5 digits then you can use:

protected static $rules = [
    'zip_code' => 'required|digits:5|integer'
];

Although in last case, zipcodes with leading zeroes will be trimmed and that's why for zipcodes I recommend using preg_match for validation. Define a custom validation rule in your AppServiceProvider file under boot function. For reference see this:

https://laravel.com/docs/5.3/validation#custom-validation-rules

and you should use varchar(10)(string,10 in laravel) instead of integer for zipcodes because:

  1. You cannot define size of integer in MySQL but you can for varchar.

  2. Zip codes can be 10 characters long with extension(zip+4, ex: 12345-1234).

I hope it helps

Abhay Maurya
  • 11,819
  • 8
  • 46
  • 64
0

The above regex of \b\d{5}\b uses word boundaries and would pass validation as long as there are 5 grouped digits anywhere in the input. This is probably not what most people want.

For example, if the user submits Hello 00000 World!, validation would pass and your controller would receive the string Hello 00000 World! which is most likely not what it would be expecting and it would cry.


Validate 5 Digits (Zip)

I would suggest using anchors since all we want is 5 digits and absolutely nothing else to pass validation and in to the controller.

Something like this is simple and would work for 5 digits (a zip code):

protected static $rules = [
    'zip_code' => 'required|regex:/^\d{5}$/'
];

Validate 5 Digits a dash, and 4 Digits (Zip + 4)

Or, if you want to validate Zip+4, ie. 12345-6789 formatted zip codes you could do something like this:

protected static $rules = [
    'zip_code' => 'required|regex:/^\d{5}-\d{4}$/'
];

That would let 12345-6789 through, but not 1234-56789 or 123456789, etc.

Then something like this to handle it:

$zip = explode('-', $request->input('zip_code'));

$zip[0] would have 12345, which is the zip.

$zip[1] would have 6789, which is the +4.


Validate Either (Zip or Zip + 4)

Or, let's say you want to accept and validate either zip or zip+4 depending on what the user submitted. You could do something like this:

protected static $rules = [
    'zip_code' => 'required|regex:/^\d{5}(?:-\d{4})?$/'
];

That would let 12345 and 12345-6789 but fail on anything else.

Then you could the same as above since explode will still work on both variants but build an array of either one or two values depending.

$zip = explode('-', $request->input('zip_code'));

if (count($zip) > 1) {
    // do some zip+4 stuff
} else {
    // just a zip, lets do zip stuff
}
Giovanni S
  • 2,050
  • 18
  • 33
-3

You getting this wrong instead on size:5 try min:5|max:5

  • Using `min` or `max` on any numerical field will require that field to be between the `min` and `max`. For example, if you set `min:5` and `max:5`, the number can only be five. If you set `min:3` and `max:10`, the number can only be 3 - 10. See https://laravel.com/docs/8.x/validation#rule-size – Marc Feb 01 '22 at 02:49