php 40 lines · 6 steps

How a custom phone validation rule works in Laravel

A Laravel ValidationRule wraps libphonenumber to parse and validate phone numbers against a default region.

Explained by highlit
1<?php
2 
3namespace App\Rules;
4 
5use Closure;
6use Illuminate\Contracts\Validation\ValidationRule;
7use libphonenumber\NumberParseException;
8use libphonenumber\PhoneNumberUtil;
9 
10class ValidPhoneNumber implements ValidationRule
11{
12 public function __construct(
13 private readonly ?string $defaultRegion = 'US',
14 ) {
15 }
16 
17 public function validate(string $attribute, mixed $value, Closure $fail): void
18 {
19 if (! is_string($value) || trim($value) === '') {
20 $fail('The :attribute must be a valid phone number.')->translate();
21 
22 return;
23 }
24 
25 $util = PhoneNumberUtil::getInstance();
26 
27 try {
28 $number = $util->parse($value, $this->defaultRegion);
29 } catch (NumberParseException) {
30 $fail('The :attribute is not a recognizable phone number.')->translate();
31 
32 return;
33 }
34 
35 if (! $util->isValidNumber($number)) {
36 $fail('The :attribute is not a valid phone number for the :region region.')
37 ->translate(['region' => $this->defaultRegion]);
38 }
39 }
40}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Implementing ValidationRule lets you encapsulate complex domain checks as a reusable, injectable object.
  2. 2Calling $fail and returning early keeps each failure path isolated and prevents downstream code from running on bad input.
  3. 3Delegating phone parsing to libphonenumber gives you region-aware correctness instead of fragile regex guesses.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How a custom phone validation rule works in Laravel — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code