Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Libphonenumber For Php Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require giggsey/libphonenumber-for-php
    

    Ensure mbstring extension is enabled in your php.ini.

  2. First Use Case: Parse and validate a phone number:

    use libphonenumber\PhoneNumberUtil;
    
    $phoneUtil = PhoneNumberUtil::getInstance();
    $number = $phoneUtil->parse('+1 650 253 0000', null);
    $isValid = $phoneUtil->isValidNumber($number);
    
  3. Key Classes to Explore:

    • PhoneNumberUtil (core parsing/formatting)
    • PhoneNumberOfflineGeocoder (location lookup)
    • PhoneNumberToCarrierMapper (carrier identification)

Implementation Patterns

Core Workflows

  1. Validation & Parsing:

    $phoneUtil = PhoneNumberUtil::getInstance();
    try {
        $number = $phoneUtil->parse($rawInput, $regionCode);
        if ($phoneUtil->isValidNumber($number)) {
            // Proceed with valid number
        }
    } catch (NumberParseException $e) {
        // Handle invalid format
    }
    
  2. Formatting for Display:

    // E164 (international standard): +442071838750
    $e164 = $phoneUtil->format($number, PhoneNumberFormat::E164);
    
    // National format (e.g., "020 7183 8750" for UK)
    $national = $phoneUtil->format($number, PhoneNumberFormat::NATIONAL);
    
    // International format (e.g., "+44 20 7183 8750")
    $international = $phoneUtil->format($number, PhoneNumberFormat::INTERNATIONAL);
    
  3. Geocoding:

    $geocoder = PhoneNumberOfflineGeocoder::getInstance();
    $location = $geocoder->getDescriptionForNumber($number, 'en_US');
    
  4. Carrier Lookup:

    $carrierMapper = PhoneNumberToCarrierMapper::getInstance();
    $carrierName = $carrierMapper->getNameForNumber($number, 'en');
    

Laravel Integration Tips

  1. Service Provider: Register the package in AppServiceProvider:

    public function boot()
    {
        $this->app->singleton(PhoneNumberUtil::class, function () {
            return PhoneNumberUtil::getInstance();
        });
    }
    
  2. Request Validation: Use in Laravel Form Requests:

    use libphonenumber\PhoneNumberUtil;
    use libphonenumber\NumberParseException;
    
    public function rules()
    {
        return [
            'phone' => 'required|phone_number'
        ];
    }
    
    public function validatePhone($attribute, $value, $fail)
    {
        $phoneUtil = app(PhoneNumberUtil::class);
        try {
            $number = $phoneUtil->parse($value);
            if (!$phoneUtil->isValidNumber($number)) {
                $fail('The :attribute is invalid.');
            }
        } catch (NumberParseException $e) {
            $fail('The :attribute is invalid.');
        }
    }
    
  3. Model Casting: Cast phone numbers in Eloquent models:

    use libphonenumber\PhoneNumberUtil;
    use libphonenumber\PhoneNumberFormat;
    
    protected $casts = [
        'phone' => PhoneNumberCast::class,
    ];
    
    // Custom Cast Class
    class PhoneNumberCast implements AttributeCast
    {
        public function get($model, string $key, $value, array $attributes)
        {
            return $value;
        }
    
        public function set($model, string $key, $value, array $attributes)
        {
            $phoneUtil = app(PhoneNumberUtil::class);
            $number = $phoneUtil->parse($value);
            return $phoneUtil->format($number, PhoneNumberFormat::E164);
        }
    }
    
  4. API Responses: Format numbers consistently in API responses:

    return response()->json([
        'phone' => $phoneUtil->format($user->phoneNumber, PhoneNumberFormat::E164)
    ]);
    

Gotchas and Tips

Pitfalls

  1. Region Code Ambiguity:

    • Omitting the region code (e.g., parsing +44...) may yield unexpected results if the number could belong to multiple regions.
    • Fix: Always specify the region code when possible (e.g., parse('020...', 'GB')).
  2. Invalid Numbers:

    • parse() throws NumberParseException for malformed input, but isValidNumber() checks logical validity (e.g., does the number exist for the region?).
    • Tip: Combine both checks:
      try {
          $number = $phoneUtil->parse($input);
          if (!$phoneUtil->isValidNumber($number)) {
              throw new \InvalidArgumentException('Invalid phone number.');
          }
      } catch (NumberParseException $e) {
          throw new \InvalidArgumentException('Malformed phone number.');
      }
      
  3. Geocoding Limitations:

    • Offline geocoding relies on static metadata. For dynamic or high-precision needs, consider integrating with a third-party API.
    • Workaround: Use PhoneNumberOfflineGeocoder for basic city-level resolution, then supplement with external services for street addresses.
  4. Carrier Mapping:

    • Not all countries support carrier mapping. Check with PhoneNumberToCarrierMapper::getInstance()->isSupportedRegion($regionCode).
    • Tip: Fall back to generic region-based carriers if specific mapping fails.
  5. Performance:

    • The library loads metadata on first use, which can be slow (~500ms). Cache the singleton instances:
      $phoneUtil = PhoneNumberUtil::getInstance(); // Load once at app startup
      

Debugging Tips

  1. Inspect Parsed Numbers: Use var_dump($number) to debug PhoneNumber objects. Key properties:

    • countryCode: E.g., 44 for UK.
    • nationalNumber: E.g., 2071838750 for 020 7183 8750.
    • extension: If present, e.g., x123.
  2. Common Exceptions:

    • NumberParseException: Invalid format (e.g., parse('abc', 'GB')).
    • NumberFormatException: Invalid format specifier (e.g., format($number, 999)).
  3. Locale-Specific Issues:

    • Geocoding descriptions vary by locale (e.g., en_US vs. de_DE). Test with target locales early.

Extension Points

  1. Custom Formatting: Extend PhoneNumberUtil for project-specific formats:

    class CustomPhoneNumberUtil extends PhoneNumberUtil
    {
        public function formatCustom($number)
        {
            return '(' . substr($this->format($number, PhoneNumberFormat::NATIONAL), 0, 4) . ') ' .
                   substr($this->format($number, PhoneNumberFormat::NATIONAL), 4);
        }
    }
    
  2. Validation Rules: Create reusable validation logic:

    class PhoneNumberValidator
    {
        public static function validate($input, $region = null)
        {
            $phoneUtil = PhoneNumberUtil::getInstance();
            try {
                $number = $phoneUtil->parse($input, $region);
                return $phoneUtil->isValidNumber($number);
            } catch (NumberParseException) {
                return false;
            }
        }
    }
    
  3. Event Listeners: Trigger actions on phone number changes (e.g., in Laravel models):

    protected static function booted()
    {
        static::updating(function ($model) {
            if ($model->isDirty('phone')) {
                $phoneUtil = app(PhoneNumberUtil::class);
                $model->phone = $phoneUtil->format(
                    $phoneUtil->parse($model->phone),
                    PhoneNumberFormat::E164
                );
            }
        });
    }
    
  4. Testing: Mock the singleton for unit tests:

    $mockUtil = $this->createMock(PhoneNumberUtil::class);
    $mockUtil->method('parse')->willReturn($validNumber);
    $mockUtil->method('isValidNumber')->willReturn(true);
    
    $this->app->instance(PhoneNumberUtil::class, $mockUtil);
    

Configuration Quirks

  1. Metadata Updates:

    • The library bundles metadata from Google’s libphonenumber. To update:
      composer run build
      
    • Note: This requires cloning the Google repo and compiling data (~10MB download).
  2. **Memory Usage

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
phalcon/cli-options-parser
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
directorytree/privacy-filter-classifier
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata