giggsey/libphonenumber-for-php
PHP port of Google’s libphonenumber for parsing, formatting, validating, and storing international phone numbers. Supports geocoding, carrier and timezone mapping, plus short-number info. Composer install; requires mbstring.
## Getting Started
### Minimal Setup
1. **Installation**
```bash
composer require giggsey/libphonenumber-for-php:^9.0
Note: Updated to version 9.0+ to leverage latest metadata and features.
First Use Case: Validate & Parse a Phone Number
use libphonenumber\PhoneNumberUtil;
use libphonenumber\PhoneNumberFormat;
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('+919876543210', 'IN'); // Updated India metadata
// Validate and format
if ($phoneUtil->isValidNumber($number)) {
$formatted = $phoneUtil->format($number, PhoneNumberFormat::NATIONAL);
// Output: 9876543210 (India national format)
}
Key Files to Reference
vendor/giggsey/libphonenumber-for-php/src/ (Core classes, v9.0+)vendor/giggsey/libphonenumber-for-php/data/ (Updated metadata for CL, CZ, DE, IN, SG)Region-Specific Formatting (New in v9.0)
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('+49301234567', 'DE'); // Germany
// Use NATIONAL format for local display
$formatted = $phoneUtil->format($number, PhoneNumberFormat::NATIONAL);
// Output: 030 1234567 (Germany national format)
Carrier Detection (Enhanced in v9.0)
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('+56912345678', 'CL'); // Chile
$carrier = $phoneUtil->getNumberType($number);
// Returns PhoneNumberType::MOBILE, FIXED_LINE, etc.
Batch Processing with Updated Metadata
$numbers = ['+919876543210', '+420123456789', '+8613800138000'];
$results = collect($numbers)->map(function ($num) use ($phoneUtil) {
$parsed = $phoneUtil->parse($num);
return [
'number' => $parsed,
'valid' => $phoneUtil->isValidNumber($parsed),
'region' => $phoneUtil->getRegionCodeForNumber($parsed),
];
})->filter(fn($item) => $item['valid']);
Integration with Laravel Requests (v9.0 Compatibility)
use Illuminate\Http\Request;
use libphonenumber\PhoneNumberUtil;
public function store(Request $request) {
$phoneUtil = PhoneNumberUtil::getInstance();
$phone = $request->input('phone');
$parsed = $phoneUtil->parse($phone);
if (!$phoneUtil->isValidNumber($parsed)) {
return back()->withErrors(['phone' => 'Invalid number']);
}
// Store in E164 format (recommended for databases)
$this->user->phone = $phoneUtil->format($parsed, PhoneNumberFormat::E164);
// Optional: Store carrier/type for analytics
$this->user->phone_type = $phoneUtil->getNumberType($parsed)->getName();
}
Testing with Updated Regions
use libphonenumber\PhoneNumberUtil;
use PHPUnit\Framework\TestCase;
class PhoneNumberTest extends TestCase {
public function testValidIndiaNumber() {
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('+919876543210', 'IN');
$this->assertTrue($phoneUtil->isValidNumber($number));
$this->assertEquals('IN', $phoneUtil->getRegionCodeForNumber($number));
}
public function testGermanyFormatting() {
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('+49301234567', 'DE');
$this->assertEquals('030 1234567', $phoneUtil->format($number, PhoneNumberFormat::NATIONAL));
}
}
Breaking Changes in v9.0
PhoneNumberUtil::getDefaultInstance() (use getInstance()).PhoneNumberFormat::INTERNATIONAL in favor of E164 for consistency.PhoneNumberFormat::E164 or NATIONAL.Region-Specific Quirks (v9.0 Updates)
919876543210 → 9876543210).+49301234567 → 030 1234567).Performance with Carrier Data
getNumberType) is now more accurate but slightly slower.$carrierCache = Cache::remember("carrier_{$phone}", 365, function() use ($phoneUtil, $number) {
return $phoneUtil->getNumberType($number)->getName();
});
Metadata Loading Issues
CL, CZ, or SG, ensure you’re using the latest data/ files from the package.vendor/giggsey/libphonenumber-for-php/data/.Time Zone Data for Geocoding
91 (India) may affect time zone resolution.$phoneUtil->setRegionCodeForNumber($number, 'IN');
Log Updated Metadata:
$phoneUtil = PhoneNumberUtil::getInstance();
\Log::debug('Supported regions:', array_keys($phoneUtil->getSupportedRegions()));
\Log::debug('India metadata:', $phoneUtil->getMetadataForRegion('IN'));
Validate Against New Test Cases:
Use the updated test data for regions like CL, CZ, and SG from Google’s v9.0 tests.
Handle Carrier Data Changes:
$number = $phoneUtil->parse('+56912345678', 'CL');
$type = $phoneUtil->getNumberType($number);
\Log::debug('Carrier type:', $type->getName(), [
'isMobile' => $type === PhoneNumberType::MOBILE,
'isFixedLine' => $type === PhoneNumberType::FIXED_LINE,
]);
Custom Region Handling
Override region-specific logic for edge cases (e.g., toll-free numbers in IN):
$phoneUtil->setRegionCodeForNumber($number, 'IN');
$phoneUtil->setMetadataProvider(new CustomMetadataProvider([
'IN' => [
'toll_free_prefixes' => ['1800', '18000'],
],
]));
Event-Driven Validation Extend validation with carrier/type checks:
$validator = Validator::make($request->all(), [
'phone' => ['required', function ($attribute, $value, $fail) {
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse($value);
if (!$phoneUtil->isValidNumber($number)) {
$fail('Invalid phone number.');
}
// Block toll-free numbers if needed
if ($phoneUtil->getNumberType($number) === PhoneNumberType::TOLL_FREE) {
$fail('Toll-free numbers are not allowed.');
}
}],
]);
How can I help you explore Laravel packages today?