You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合并区号与手机号字段并应用PhoneNumber验证?

解决区号+手机号合并验证及错误提示问题

你当前的问题是:将区号和手机号合并后应用PhoneNumber验证,但使用隐藏字段存储合并值时,无法显示验证错误消息。以下是几种可行的解决方案:

方案一:自定义验证规则直接验证合并值

创建可接收区号参数的自定义验证规则,直接对手机号字段进行验证,错误消息会直接显示在手机号输入框下方。

步骤1:创建自定义规则

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use libphonenumber\PhoneNumberUtil;

class PhoneNumberCombined implements Rule
{
    protected $callingCode;

    public function __construct($callingCode)
    {
        $this->callingCode = $callingCode;
    }

    public function passes($attribute, $value)
    {
        // 合并区号和手机号
        $fullNumber = $this->callingCode . $value;
        $phoneUtil = PhoneNumberUtil::getInstance();

        try {
            $parsedNumber = $phoneUtil->parse($fullNumber, null);
            return $phoneUtil->isValidNumber($parsedNumber);
        } catch (\Exception $e) {
            return false;
        }
    }

    public function message()
    {
        return '请输入有效的手机号码格式';
    }
}

步骤2:在表单中应用规则

动态获取区号字段的值,将其传入自定义规则并绑定到手机号字段:

Group::make([
    Select::make('code')
        ->options(fn (PhoneNumberUtil $util) => $util->getSupportedCallingCodes())
        ->label('国家区号')
        ->required()
        ->columnSpan(5),

    TextInput::make('number')
        ->rules(['regex:/^[0-9 -]+$/'])
        ->required()
        ->columnSpan(7)
        // 动态添加合并验证规则
        ->rules(function (callable $get) {
            $code = $get('code');
            return $code ? [new \App\Rules\PhoneNumberCombined($code)] : [];
        }),
])->columns(12)

方案二:利用表单钩子合并验证并关联错误

通过Filament的beforeValidation钩子手动合并字段、执行验证,并将错误消息关联到可见的手机号字段:

public static function form(Form $form): Form
{
    return $form
        ->schema([
            Group::make([
                Select::make('code')
                    ->options(fn (PhoneNumberUtil $util) => $util->getSupportedCallingCodes())
                    ->label('国家区号')
                    ->required()
                    ->columnSpan(5),

                TextInput::make('number')
                    ->rules(['regex:/^[0-9 -]+$/'])
                    ->required()
                    ->columnSpan(7),
            ])->columns(12),
        ])
        ->beforeValidation(function (Form $form) {
            $state = $form->getState();
            $fullNumber = $state['code'] . $state['number'];

            // 手动执行验证
            $validator = \Illuminate\Support\Facades\Validator::make(
                ['contact' => $fullNumber],
                ['contact' => ['required', new \App\Rules\PhoneNumber()]]
            );

            if ($validator->fails()) {
                // 将错误消息添加到手机号字段
                $form->getComponent('number')->addError($validator->errors()->first('contact'));
                // 抛出异常阻止表单提交
                throw new \Illuminate\Validation\ValidationException($validator);
            }
        });
}

方案三:使用表单请求合并验证

创建自定义表单请求,在验证前合并字段,并将错误消息映射到可见字段:

步骤1:创建表单请求

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\ValidationException;

class StoreContactRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'code' => ['required'],
            'number' => ['required', 'regex:/^[0-9 -]+$/'],
            'contact' => ['required', new \App\Rules\PhoneNumber()],
        ];
    }

    public function prepareForValidation()
    {
        // 合并区号和手机号
        $this->merge([
            'contact' => $this->input('code') . $this->input('number'),
        ]);
    }

    protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
    {
        // 将contact字段的错误转移到number字段
        if ($validator->errors()->has('contact')) {
            $validator->errors()->add('number', $validator->errors()->first('contact'));
            $validator->errors()->forget('contact');
        }

        throw (new ValidationException($validator))
            ->errorBag($this->errorBag)
            ->redirectTo($this->getRedirectUrl());
    }
}

步骤2:在Filament资源中使用请求

public static function form(Form $form): Form
{
    return $form
        ->schema([
            Group::make([
                Select::make('code')
                    ->options(fn (PhoneNumberUtil $util) => $util->getSupportedCallingCodes())
                    ->label('国家区号')
                    ->required()
                    ->columnSpan(5),

                TextInput::make('number')
                    ->rules(['regex:/^[0-9 -]+$/'])
                    ->required()
                    ->columnSpan(7),
            ])->columns(12),
        ])
        ->formRequest(\App\Http\Requests\StoreContactRequest::class);
}

以上方案都能解决隐藏字段无法显示验证消息的问题,其中方案一的实现最简洁,错误提示直接关联到用户输入的手机号字段,用户体验最佳。

内容的提问来源于stack exchange,提问作者marin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 08:31:02