Weave 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

A PHP port of Google's libphonenumber for parsing, formatting, storing, and validating international phone numbers, with geocoding, carrier, and timezone mapping.

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.
quimgc/tasks
sistem-atc/bank-sdk
core45/laravel-cookieconsent
projectsend/community-modules
ovac/laravel-hubtel-payment
capimail/capimail-php
shiroamada/green-api-laravel-notification
shiroamada/ultrasms-laravel-notification
esazykin/laravel-clickhouse
nbrabant/laraadmin
tobya/saloonfire
kjmtrue/laravel-debugbar
hexincorp/debugbar
razorbacks/laravel-shibboleth
adilazhari/laravel-idempotency
mamitech/laravel-slow-query-log
mamitech/laravel-http-logger
medeirosrafael/docxmustache
webdevlabs/phreak
vis/log-envelope