giggsey/libphonenumber-for-php-lite
Lite PHP port of Google’s libphonenumber for parsing, formatting, storing, and validating international phone numbers. Includes core PhoneNumberUtils only (no geolocation/carrier/short numbers). Requires PHP 8.1+ and mbstring; install via Composer.
Installation:
composer require giggsey/libphonenumber-for-php-lite
Ensure mbstring extension is enabled in your PHP configuration.
First Use Case: Parse and validate a phone number:
use libphonenumber\PhoneNumberUtil;
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse('+442071838750', 'GB');
$isValid = $phoneUtil->isValidNumber($number);
Where to Look First:
Parsing and Validation:
$phoneUtil = PhoneNumberUtil::getInstance();
$number = $phoneUtil->parse($rawPhoneNumber, $regionCode);
$isValid = $phoneUtil->isValidNumber($number);
Formatting:
// E164 format (e.g., +442071838750)
$e164 = $phoneUtil->format($number, PhoneNumberFormat::E164);
// National format (e.g., 020 7183 8750 for GB)
$national = $phoneUtil->format($number, PhoneNumberFormat::NATIONAL);
// International format (e.g., +44 20 7183 8750)
$international = $phoneUtil->format($number, PhoneNumberFormat::INTERNATIONAL);
Number Type Detection:
$numberType = $phoneUtil->getNumberType($number);
// Returns constants like PhoneNumberType::MOBILE, PhoneNumberType::FIXED_LINE, etc.
Number Matching:
$isMatch = $phoneUtil->isNumberMatch($number1, $number2);
// Returns a confidence level (0-4) indicating if the numbers could be the same.
Example Numbers:
$exampleNumber = $phoneUtil->getExampleNumber('US');
$mobileExample = $phoneUtil->getExampleNumberByType('US', PhoneNumberType::MOBILE);
Laravel Request Validation: Use the package in Laravel form requests or validation rules:
use libphonenumber\PhoneNumberUtil;
$validator = Validator::make($request->all(), [
'phone' => function ($attribute, $value, $fail) {
$phoneUtil = PhoneNumberUtil::getInstance();
try {
$number = $phoneUtil->parse($value);
if (!$phoneUtil->isValidNumber($number)) {
$fail('The phone number is invalid.');
}
} catch (\libphonenumber\NumberParseException $e) {
$fail('The phone number is invalid.');
}
},
]);
Service Layer: Create a dedicated service class for phone number operations:
namespace App\Services;
use libphonenumber\PhoneNumberUtil;
use libphonenumber\PhoneNumberFormat;
class PhoneNumberService
{
protected $phoneUtil;
public function __construct()
{
$this->phoneUtil = PhoneNumberUtil::getInstance();
}
public function formatE164($phoneNumber, $regionCode)
{
$number = $this->phoneUtil->parse($phoneNumber, $regionCode);
return $this->phoneUtil->format($number, PhoneNumberFormat::E164);
}
// Add other methods as needed...
}
Model Observers/Accessors: Add phone number parsing/validation to Eloquent models:
use libphonenumber\PhoneNumberUtil;
class User extends Model
{
protected static function boot()
{
parent::boot();
static::saving(function ($user) {
$phoneUtil = PhoneNumberUtil::getInstance();
try {
$number = $phoneUtil->parse($user->phone);
$user->phone_e164 = $phoneUtil->format($number, PhoneNumberFormat::E164);
} catch (\libphonenumber\NumberParseException $e) {
// Handle exception
}
});
}
}
Region Code Sensitivity:
02071838750 without a region code might fail, but with GB it works.Exception Handling:
try-catch block to handle NumberParseException:
try {
$number = $phoneUtil->parse($rawNumber, $regionCode);
} catch (\libphonenumber\NumberParseException $e) {
// Handle invalid numbers gracefully
}
Number Type Limitations:
getNumberType() results cautiously in business logic.Short Number Limitations:
isValidShortNumber) only checks patterns, not actual usage. False positives are possible.Performance:
PhoneNumberUtil instance if initializing frequently:
$phoneUtil = PhoneNumberUtil::getInstance(); // Expensive first call
Check Raw Input:
Use $phoneUtil->getNumberType($number) and $phoneUtil->getRegionCodeForNumber($number) to debug parsing issues.
Validate with Online Tools: Cross-check results with Google's libphonenumber demo if unsure about correctness.
Log Parsed Numbers:
Log the parsed PhoneNumber object to inspect its properties (e.g., countryCode, nationalNumber):
$number = $phoneUtil->parse($rawNumber, $regionCode);
\Log::debug([
'countryCode' => $number->getCountryCode(),
'nationalNumber' => $number->getNationalNumber(),
'extension' => $number->getExtension(),
]);
Custom Formatting: Extend the library by creating custom formatters:
class CustomPhoneNumberFormatter
{
public static function formatCustom($phoneNumber)
{
$phoneUtil = PhoneNumberUtil::getInstance();
$e164 = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
// Add custom logic (e.g., append a suffix)
return $e164 . '-CUSTOM';
}
}
Region-Specific Logic:
Use the PhoneNumberUtil to implement region-specific business rules:
$regionCode = $phoneUtil->getRegionCodeForNumber($number);
if ($regionCode === 'US') {
// Apply US-specific logic
}
Carrier Mapping (if needed):
Although this is the "lite" version, you can still use the PhoneNumberToCarrierMapper for carrier names:
$carrierMapper = \libphonenumber\PhoneNumberToCarrierMapper::getInstance();
$carrierName = $carrierMapper->getNameForNumber($number, 'en');
Metadata Updates:
libphonenumber-for-php package.Language Support:
'en') when using getNameForNumber().Short Number Costs:
ShortNumberCost::UNKNOWN_COST as a fallback.How can I help you explore Laravel packages today?