如何合并区号与手机号字段并应用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
相关产品推荐
相关产品推荐

