Installation
composer require giggsey/libphonenumber-for-php
Add to composer.json if using a monorepo or custom setup:
"repositories": [
{
"type": "vcs",
"url": "https://github.com/giggsey/libphonenumber-for-php"
}
]
First Use Case: Validate & Parse a Phone Number
use libphonenumber\PhoneNumberUtil;
use libphonenumber\PhoneNumberFormat;
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('+14155552671', 'US'); // Parse with region
// Validate and format
if ($phoneUtil->isValidNumber($number)) {
$formatted = $phoneUtil->format($number, PhoneNumberFormat::E164);
// Output: +14155552671
}
Key Files to Reference
vendor/giggsey/libphonenumber-for-php/src/ (Core classes)vendor/giggsey/libphonenumber-for-php/data/ (Phone metadata)Validation & Sanitization
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parseAndValidate('123-456-7890', 'US');
// Returns null if invalid, otherwise a PhoneNumber object
Geocoding & Region Detection
$regionCode = $phoneUtil->getRegionCodeForNumber($number);
$nationalNumber = $phoneUtil->getNationalSignificantNumber($number);
Batch Processing
$numbers = ['+442071838750', '1234567890'];
$results = collect($numbers)->map(function ($num) use ($phoneUtil) {
return $phoneUtil->parse($num, 'GB') ?: null;
})->filter();
Integration with Laravel Requests
use Illuminate\Http\Request;
public function store(Request $request) {
$phoneUtil = PhoneNumberUtil::getInstance();
$phone = $request->input('phone');
$parsed = $phoneUtil->parse($phone, 'US');
if (!$phoneUtil->isValidNumber($parsed)) {
return back()->withErrors(['phone' => 'Invalid number']);
}
// Store E164 format
$this->user->phone = $phoneUtil->format($parsed, PhoneNumberFormat::E164);
}
Testing
use libphonenumber\PhoneNumberUtil;
use PHPUnit\Framework\TestCase;
class PhoneNumberTest extends TestCase {
public function testValidUSNumber() {
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('+14155552671', 'US');
$this->assertTrue($phoneUtil->isValidNumber($number));
}
}
Region Ambiguity
parse('1234567890')) defaults to PhoneNumberUtil::DEFAULT_REGION.$number = $phoneUtil->parse('02071838750'); // UK vs. other regions
$region = $phoneUtil->getRegionCodeForNumber($number);
Performance with Large Datasets
// ❌ Bad (creates new instance per call)
$phoneUtil->parse(...);
// ✅ Good (reuse instance)
$phoneUtil = PhoneNumberUtil::getInstance();
Edge Cases in Validation
isPossibleNumber() for lenient checks:
if (!$phoneUtil->isPossibleNumber($number)) {
// Handle potential invalid formats
}
Time Zone Data
Deprecated Methods
PhoneNumberUtil::getDefaultInstance() (use getInstance()).PhoneNumberFormat::E164 over PhoneNumberFormat::INTERNATIONAL.Log Parsed Numbers:
$number = $phoneUtil->parse('+442071838750');
\Log::debug('Parsed:', [
'number' => $number->getNationalNumber(),
'region' => $phoneUtil->getRegionCodeForNumber($number),
'valid' => $phoneUtil->isValidNumber($number),
]);
Test with Known Values: Use Google’s test data to verify edge cases.
Custom Metadata Override default phone metadata (e.g., for internal extensions):
$phoneUtil->setMetadataProvider(new CustomMetadataProvider());
Event Hooks Extend validation logic via closures:
$validator = Validator::make($request->all(), [
'phone' => ['required', function ($attribute, $value, $fail) {
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse($value);
if (!$phoneUtil->isValidNumber($number)) {
$fail('The '.$attribute.' must be a valid phone number.');
}
}],
]);
Caching
Cache PhoneNumberUtil instance in Laravel’s cache:
$phoneUtil = Cache::remember('phoneUtil', 365 * 24 * 60, function() {
return PhoneNumberUtil::getInstance();
});
How can I help you explore Laravel packages today?