joepages/laravel-phone-numbers 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

joepages/laravel-phone-numbers

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.

joepages/laravel-phone-numbers 适用场景与选型建议

joepages/laravel-phone-numbers 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 347 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 02 月 02 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「polymorphic」 「multi-tenancy」 「phone-numbers」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 joepages/laravel-phone-numbers 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 joepages/laravel-phone-numbers 我们能提供哪些服务?
定制开发 / 二次开发

基于 joepages/laravel-phone-numbers 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

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

GitHub 信息

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

其他信息

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