Installation Add the bundle via Composer:
composer require odolbeau/phone-number-bundle
Enable the bundle in config/bundles.php (Symfony) or config/app.php (Laravel via Symfony bridge):
Odolbeau\PhoneNumberBundle\OdolbeauPhoneNumberBundle::class => ['all' => true],
Configuration
Publish the default config (if needed) and adjust in config/packages/odolbeau_phone_number.yaml:
odolbeau_phone_number:
default_locale: 'en'
default_region: 'US'
First Use Case Validate and parse a phone number in a controller or service:
use Odolbeau\PhoneNumberBundle\PhoneNumber;
$phoneNumber = PhoneNumber::parse('+1 555 123 4567', 'US');
$isValid = $phoneNumber->isValid(); // true/false
$formatted = $phoneNumber->format(); // "+15551234567"
Validation
Use PhoneNumber::parse() to validate and normalize numbers:
$number = PhoneNumber::parse($rawInput, $region);
if (!$number->isValid()) {
throw new \InvalidArgumentException("Invalid phone number");
}
Form Integration (Symfony/Laravel)
Create a custom validator or use Symfony’s PhoneNumberValidator:
// Symfony Form Type
use Odolbeau\PhoneNumberBundle\Validator\Constraints as PhoneAssert;
$builder->add('phone', TextType::class, [
'constraints' => [
new PhoneAssert\PhoneNumber(['region' => 'FR'])
]
]);
Geocoding & Region Detection Detect a number’s region or geocode it:
$number = PhoneNumber::parse('+44 20 1234 5678');
$region = $number->getRegionCode(); // 'GB'
$isMobile = $number->isMobile(); // true/false
Batch Processing Process arrays of numbers (e.g., CSV imports):
$numbers = ['+15551234567', '442012345678'];
$validNumbers = array_filter($numbers, fn($n) => PhoneNumber::parse($n)->isValid());
Localization Format numbers for display in a specific locale:
$number->format('NATIONAL'); // "555-123-4567" (US)
$number->format('INTERNATIONAL'); // "+1 555 123 4567"
symfony/flex) or wrap the bundle in a Laravel service provider.PhoneNumber in unit tests:
$this->assertTrue(PhoneNumber::parse('+15551234567')->isValid());
Region Ambiguity
Some numbers (e.g., +1 212 555 1234) may resolve to multiple regions. Use getPossibleNumbers() to handle ambiguity:
$possibleNumbers = PhoneNumber::parse('+1 212 555 1234', 'US')->getPossibleNumbers();
Locale vs. Region
locale affects formatting (e.g., de for German formatting).region affects validation (e.g., US for US numbers).
Confusing them causes validation/formatting mismatches.Edge Cases
123) may pass validation but lack region context. Explicitly set a region:
PhoneNumber::parse('123', 'US'); // Validates as US short code
Performance Parsing is lightweight, but avoid parsing the same number repeatedly in loops. Cache results:
$cache = new \Symfony\Component\Cache\Simple\FilesystemCache();
$cachedNumber = $cache->get($rawNumber, fn() => PhoneNumber::parse($rawNumber));
PhoneNumber::parse()->isValid() to catch issues early.NATIONAL, E164, etc.).config/packages/odolbeau_phone_number.yaml:
debug: true
Custom Rules Extend validation with a custom validator:
use Odolbeau\PhoneNumberBundle\PhoneNumber;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class CustomPhoneValidator extends ConstraintValidator {
public function validate($value, Constraint $constraint) {
$number = PhoneNumber::parse($value);
if (!$number->isMobile()) {
$this->context->buildViolation('Must be a mobile number')->addViolation();
}
}
}
Override Defaults
Extend the bundle’s config or create a decorator for PhoneNumber:
// app/PhoneNumberDecorator.php
class PhoneNumberDecorator extends \Odolbeau\PhoneNumberBundle\PhoneNumber {
public function isTollFree() {
return $this->getNationalNumber() === 800; // Example
}
}
Database Storage
Store numbers in E164 format (e.g., +15551234567) for consistency:
$e164 = PhoneNumber::parse($input)->format('E164');
How can I help you explore Laravel packages today?