php 53 lines · 8 steps

Normalizing phone numbers to E.164 in PHP

A static helper cleans arbitrary phone input, applies a country prefix, and validates it against the E.164 format.

Explained by highlit
1<?php
2 
3namespace App\Support;
4 
5use InvalidArgumentException;
6 
7final class PhoneNumber
8{
9 private const COUNTRY_PREFIXES = [
10 'US' => '1',
11 'GB' => '44',
12 'FR' => '33',
13 'DE' => '49',
14 'IN' => '91',
15 ];
16 
17 public static function toE164(string $input, string $defaultRegion = 'US'): string
18 {
19 $trimmed = trim($input);
20 $hasPlus = str_starts_with($trimmed, '+');
21 $digits = preg_replace('/\D+/', '', $trimmed);
22 
23 if ($digits === '' || strlen($digits) < 8) {
24 throw new InvalidArgumentException("Phone number '{$input}' has too few digits.");
25 }
26 
27 if (!$hasPlus) {
28 $digits = self::applyDefaultRegion($digits, $defaultRegion);
29 }
30 
31 if (strlen($digits) > 15) {
32 throw new InvalidArgumentException("Phone number '{$input}' exceeds the E.164 maximum length.");
33 }
34 
35 return '+' . $digits;
36 }
37 
38 private static function applyDefaultRegion(string $digits, string $region): string
39 {
40 $prefix = self::COUNTRY_PREFIXES[strtoupper($region)]
41 ?? throw new InvalidArgumentException("Unsupported default region '{$region}'.");
42 
43 if ($region === 'US' && strlen($digits) === 11 && str_starts_with($digits, '1')) {
44 return $digits;
45 }
46 
47 if (str_starts_with($digits, $prefix) && strlen($digits) > 10) {
48 return $digits;
49 }
50 
51 return $prefix . ltrim($digits, '0');
52 }
53}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Strip formatting to raw digits first, then reason about the number as a canonical string.
  2. 2Length bounds and a known-prefix lookup catch most malformed input before it propagates.
  3. 3Handling the leading-plus case separately lets you infer a region only when the caller didn't specify one.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Normalizing phone numbers to E.164 in PHP — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code