承接 joepages/laravel-phone-numbers 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

joepages/laravel-phone-numbers

最新稳定版本:v1.1.0

Composer 安装命令:

composer require joepages/laravel-phone-numbers

包简介

Polymorphic phone numbers package for Laravel - Attach N phone numbers to any model

README 文档

README

Tests Latest Version on Packagist License

Polymorphic phone numbers for Laravel. Attach multiple phone numbers to any Eloquent model with full CRUD, bulk sync, primary management, E.164 formatting, and multi-tenancy awareness.

Requirements

  • PHP 8.2+
  • Laravel 11 or 12

Installation

composer require joepages/laravel-phone-numbers

Run the install command to publish the config and migrations:

php artisan phone-numbers:install
php artisan migrate

The installer auto-detects stancl/tenancy and publishes migrations to database/migrations/tenant/ when present.

Install options

php artisan phone-numbers:install --force            # Overwrite existing files
php artisan phone-numbers:install --skip-migrations  # Only publish config

Quick Start

1. Add the trait to your model

use PhoneNumbers\Concerns\HasPhoneNumbers;

class Facility extends Model
{
    use HasPhoneNumbers;
}

2. Add the controller trait

use PhoneNumbers\Concerns\ManagesPhoneNumbers;

class FacilityController extends BaseApiController
{
    use ManagesPhoneNumbers;
}

3. Register routes

Route::phoneNumberRoutes('facilities', FacilityController::class);

This registers the following routes:

Method URI Action
GET /facilities/{facility}/phone-numbers listPhoneNumbers
POST /facilities/{facility}/phone-numbers storePhoneNumber
PUT /facilities/{facility}/phone-numbers/{phoneNumber} updatePhoneNumber
DELETE /facilities/{facility}/phone-numbers/{phoneNumber} deletePhoneNumber

Model Trait API

The HasPhoneNumbers trait provides three relationships on your model:

$facility->phoneNumbers;                 // All phone numbers (MorphMany)
$facility->primaryPhoneNumber;           // Primary phone number (MorphOne)
$facility->phoneNumbersOfType('mobile'); // Filtered by type (MorphMany)

PhoneNumber Model

Fields

Field Type Description
type string Phone type (mobile, home, work, fax, other)
is_primary boolean Whether this is the primary phone number
country_code string Compound dial code + ISO country (e.g. +1:US, +44:GB) or plain dial code (+1)
number string Phone number digits
extension string|null Extension number
formatted string|null Display-formatted number (e.g. (555) 123-4567)
is_verified boolean Whether the number has been verified
metadata array|null Custom JSON data

Scopes

PhoneNumber::primary()->get();           // Only primary numbers
PhoneNumber::ofType('mobile')->get();    // Filter by type
PhoneNumber::forModel($facility)->get(); // All numbers for a specific model
PhoneNumber::verified()->get();          // Only verified numbers

Helpers

$phone->markAsPrimary();   // Sets as primary, unsets all others for the same parent
$phone->e164;              // "+15551234567" (E.164 format)
$phone->full_number;       // "(555) 123-4567 ext. 200" (formatted + extension)
$phone->dial_code;         // "+1" (dial code portion of country_code)
$phone->iso_country_code;  // "US" (ISO portion of compound country_code, or null)

Country Code Format

The country_code field supports a compound format +{dialCode}:{isoCode} that pairs the dial code with the ISO 3166-1 alpha-2 country code. This disambiguates countries that share the same dial code (e.g. US and Canada both use +1).

Format Example Dial Code ISO Code
Compound +1:US +1 US
Compound +1:CA +1 CA
Compound +44:GB +44 GB
Plain (legacy) +1 +1 null

The compound format is recommended. Plain dial codes are still supported for backwards compatibility but iso_country_code will return null.

Controller Trait

The ManagesPhoneNumbers trait provides two integration modes:

Standalone CRUD

Use the storePhoneNumber, updatePhoneNumber, deletePhoneNumber, and listPhoneNumbers methods directly via the route macro.

Bulk Sync via BaseApiController

When your controller extends BaseApiController, the attachPhoneNumber() method is called automatically during store() and update(). Send a phone_numbers array in the request body:

{
  "name": "Main Facility",
  "phone_numbers": [
    {
      "id": 1,
      "country_code": "+1:US",
      "number": "5559999999",
      "formatted": "(555) 999-9999"
    },
    {
      "country_code": "+44:GB",
      "number": "2071234567",
      "type": "work",
      "is_primary": true
    }
  ]
}
  • Records with an id are updated
  • Records without an id are created
  • Existing records not included in the array are deleted

API Resource

Add phone numbers to your JSON responses:

use PhoneNumbers\Concerns\WithPhoneNumbersResource;

class FacilityResource extends JsonResource
{
    use WithPhoneNumbersResource;

    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            ...$this->phoneNumbersResource(),
        ];
    }
}

Validation

The PhoneNumberRequest form request validates:

Field Rules
country_code required, string, max:10
number required, string, max:20
extension nullable, string, max:10
formatted nullable, string, max:30
type sometimes, string (validated against config when allow_custom_types is false)
is_primary sometimes, boolean
is_verified sometimes, boolean
metadata nullable, array

Configuration

// config/phone-numbers.php

return [
    // 'auto' detects stancl/tenancy, 'single' or 'multi' to force
    'tenancy_mode' => 'auto',

    // Allowed phone number types
    'types' => ['mobile', 'home', 'work', 'fax', 'other'],

    // Default type when none specified
    'default_type' => 'mobile',

    // When false, only types in the 'types' array are accepted
    'allow_custom_types' => true,
];

Database Schema

CREATE TABLE phone_numbers (
    id             BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    phoneable_type VARCHAR(255) NOT NULL,
    phoneable_id   BIGINT UNSIGNED NOT NULL,
    type           VARCHAR(50) DEFAULT 'mobile',
    is_primary     BOOLEAN DEFAULT FALSE,
    country_code   VARCHAR(10) NOT NULL,
    number         VARCHAR(255) NOT NULL,
    extension      VARCHAR(255) NULL,
    formatted      VARCHAR(255) NULL,
    is_verified    BOOLEAN DEFAULT FALSE,
    metadata       JSON NULL,
    created_at     TIMESTAMP NULL,
    updated_at     TIMESTAMP NULL,

    INDEX (phoneable_type, phoneable_id),
    INDEX (type),
    INDEX (is_primary),
    INDEX (number)
);

Testing

composer test

License

MIT License. See LICENSE for details.

统计信息

  • 总下载量: 339
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 5
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-02

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固