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

Phone Number Bundle Laravel Package

misd/phone-number-bundle

Symfony bundle integrating Google’s libphonenumber via giggsey/libphonenumber-for-php. Provides services and helpers to parse, validate, format, and geocode phone numbers in Symfony 2–4 apps. Abandoned; use odolbeau/phone-number-bundle instead.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel

Since this bundle is Symfony-specific, direct integration into Laravel requires abstraction. Start by installing the underlying library (giggsey/libphonenumber-for-php) via Composer:

composer require giggsey/libphonenumber-for-php

First Use Case: Parsing and Validating a Phone Number

use libphonenumber\PhoneNumberUtil;
use libphonenumber\PhoneNumberFormat;

// Initialize the utility (Laravel service container)
$phoneUtil = PhoneNumberUtil::getInstance();

// Parse a raw string
$phoneNumber = $phoneUtil->parse('+442071838750', 'GB');

// Format for display
echo $phoneUtil->format($phoneNumber, PhoneNumberFormat::NATIONAL);
// Output: "020 7183 8750"

Key Laravel-Specific Setup:

  1. Service Provider: Register PhoneNumberUtil in AppServiceProvider:

    public function register()
    {
        $this->app->singleton(PhoneNumberUtil::class, function () {
            return PhoneNumberUtil::getInstance();
        });
    }
    
  2. Helper Methods: Create a facade or helper class to wrap common operations:

    // app/Helpers/PhoneHelper.php
    class PhoneHelper
    {
        public static function parse(string $number, string $region = 'GB'): \libphonenumber\PhoneNumber
        {
            return app(PhoneNumberUtil::class)->parse($number, $region);
        }
    }
    

Implementation Patterns

Core Workflows

1. Parsing and Formatting

  • Use Case: Normalize user input (e.g., "+1 (212) 555-1234"+12125551234).
  • Pattern: Chain parsing + formatting in a service:
    $normalized = PhoneHelper::parse($rawInput, 'US')
        ->setNationalNumber($phoneUtil->getNationalNumber($normalized));
    

2. Validation

  • Use Case: Ensure phone numbers match expected types (e.g., mobile-only fields).
  • Pattern: Reuse Symfony’s validator logic via a custom Laravel validator:
    use libphonenumber\PhoneNumberType;
    
    class PhoneValidator extends Validator
    {
        public function validateMobile(string $number, string $region = 'GB'): bool
        {
            $phone = PhoneHelper::parse($number, $region);
            return PhoneNumberType::MOBILE === $phoneUtil->getNumberType($phone);
        }
    }
    

3. Database Storage

  • Use Case: Store phone numbers in E.164 format (e.g., varchar(35)).
  • Pattern: Use a custom Doctrine-like type (Laravel’s Attribute or Cast):
    // app/Models/User.php
    use Illuminate\Database\Eloquent\Casts\Attribute;
    
    class User extends Model
    {
        protected function phoneNumber(): Attribute
        {
            return Attribute::make(
                get: fn ($value) => PhoneHelper::parse($value),
                set: fn ($value) => $value->getE164Number()
            );
        }
    }
    

4. Forms (Laravel Collective)

  • Use Case: Create user-friendly phone input fields.
  • Pattern: Extend FormRequest or use a custom rule:
    use Illuminate\Validation\Rule;
    
    $request->validate([
        'phone' => [
            'required',
            Rule::custom(function ($attribute, $value, $fail) {
                if (!PhoneHelper::validate($value, 'GB')) {
                    $fail('Invalid phone number.');
                }
            }),
        ],
    ]);
    

5. Geocoding/Carrier Lookup

  • Use Case: Enrich phone numbers with metadata (e.g., carrier, timezone).
  • Pattern: Lazy-load services via Laravel’s container:
    $carrier = app(\libphonenumber\PhoneNumberToCarrierMapper::class)
        ->getNumberTypeForValidNumber(PhoneHelper::parse($number));
    

Integration Tips

  1. Twig Alternative: Use Blade directives for formatting:

    // app/Providers/AppServiceProvider.php
    Blade::directive('phone', function ($expression) {
        return "<?php echo app('phoneUtil')->format({$expression}, libphonenumber\PhoneNumberFormat::NATIONAL); ?>";
    });
    

    Usage:

    @phone($user->phoneNumber)
    
  2. Testing: Mock PhoneNumberUtil in tests:

    $this->partialMock(PhoneNumberUtil::class, ['parse'])
        ->shouldReceive('parse')
        ->andReturn($mockPhoneNumber);
    
  3. Performance: Cache parsed numbers if reused frequently:

    Cache::remember("phone_{$number}", 3600, function () use ($number) {
        return PhoneHelper::parse($number);
    });
    

Gotchas and Tips

Pitfalls

  1. Region Ambiguity:

    • Issue: Parsing without a region (e.g., PhoneNumberUtil::UNKNOWN_REGION) may fail for ambiguous numbers (e.g., 123 could be US or UK).
    • Fix: Always specify a default region (e.g., 'GB' for UK-centric apps).
  2. Database Migration:

    • Issue: Existing varchar columns may store malformed numbers (e.g., "0123456789" instead of "+44123456789").
    • Fix: Use a migration to normalize data:
      DB::table('users')->update([
          'phone_number' => DB::raw("REPLACE(phone_number, '0', '+44')")
      ]);
      
  3. Form Widget Quirks:

    • Issue: The country_choice widget requires manual country code mapping (e.g., 'GB''United Kingdom').
    • Fix: Override translations in resources/lang/en/validation.php:
      'phone_number' => [
          'country_GB' => 'United Kingdom',
      ],
      
  4. Deprecated Features:

    • Issue: The bundle uses Symfony-specific classes (e.g., PhoneNumberFormatHelper). Laravel must replace these with custom logic.
    • Fix: Ignore deprecated Symfony classes and focus on the core libphonenumber API.
  5. Edge Cases:

    • Issue: Numbers like "0" or "123" may pass validation but are invalid.
    • Fix: Add a custom rule:
      Rule::custom('phone', function ($attribute, $value) {
          return strlen($value) > 3 && !str_starts_with($value, '0');
      }),
      

Debugging Tips

  1. Validation Errors:

    • Use PhoneNumberUtil::isValidNumber() to debug:
      if (!$phoneUtil->isValidNumber($phoneNumber)) {
          $errors = $phoneUtil->getErrorMessage($phoneNumber);
          // Log or display $errors
      }
      
  2. Time Zone/Carrier Lookup:

    • Check if the service is available (requires libphonenumber >=5.8.8):
      try {
          $timeZones = app(\libphonenumber\PhoneNumberToTimeZonesMapper::class)
              ->getTimeZonesForValidNumber($phoneNumber);
      } catch (\Exception $e) {
          // Fallback logic
      }
      
  3. Performance Bottlenecks:

    • Avoid parsing the same number repeatedly. Cache results:
      Cache::remember("parsed_{$number}", now()->addHours(1), function () use ($number) {
          return PhoneHelper::parse($number);
      });
      

Extension Points

  1. Custom PhoneNumberType:

    • Extend the validator to support app-specific rules (e.g., "must be a UK mobile"):
      class UkMobileValidator extends PhoneValidator
      {
          public function validate(string $number): bool
          {
              $phone = PhoneHelper::parse($number, 'GB');
              return $phoneUtil->getNumberType($phone) === PhoneNumberType::MOBILE
                  && $phoneUtil->getRegionCodeForNumber($phone) === 'GB';
          }
      }
      
  2. Geocoding Integration:

    • Combine with a geocoding API (e.g., Google Maps) for location data:
      $geoData = app(\libphonenumber\PhoneNumberOfflineGeocoder::class)
          ->getRegionCodeForValidNumber($phoneNumber);
      $location = GeocodingService::reverse($geoData);
      
  3. Event Listeners:

    • Trigger events on phone number changes (e.g., send SMS verification):
      event(new PhoneNumberUpdated($user, $oldNumber, $newNumber));
      
  4. Testing Utilities:

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.
croct/coding-standard
croct/plug-php
nqxcode/phpmorphy
boundwize/pyrameter
testo/facade
headercat/phpstan-extension-ide-helper
yosymfony/parser-utils
innmind/black-box
babenkoivan/elastic-migrations
babenkoivan/elastic-adapter
develia/commons
dmstr/symfony-system-resources-bundle
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
renatomarinho/laravel-page-speed
develia/geo-bundle
austinheap/laravel-database-encryption
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle