Home > OS >  How to validate unique tel in array values when update multiple records
How to validate unique tel in array values when update multiple records

Time:08-31

When updating multiple records , I need to check tel field is unique (except id's tel).
I know to use this to validate specified id

'tel' => 'unique:dtb_users,tel,'.$user->id

but multiple is not

$validator = Validator::make($request->all(), [
    'tel.*' => [
        'nullable',
        'min:10',
        'max:12',
        'unique:dtb_users,tel' <- stuck here
    ]
]);

My form has more fields , here is two of those(in foreach loop)

<div >
    <input id="email_{{$user->id}}" name="email[{{$user->id}}]" type="email" data-id="{{ $user->id }}" email.$user->id") ? ' is-invalid' : '' }} input_change" value="{{ $old['email'][$user->id] ?? $user->email }}" placeholder="{{__('user.email_placeholder')}}" disabled>
    @if ($errors->has("email.$user->id"))
        <span  role="alert">
            <strong>{{ $errors->first("email.$user->id") }}</strong>
        </span>
    @endif
</div>
<div >
    <input id="tel_{{ $user->id }}" name="tel[{{ $user->id }}]"  value="{{ $old['tel'][$user->id] ?? $user->tel }}" placeholder="00000000000" disabled>
    @if ($errors->has("tel.$user->id"))
        <span  role="alert">
            <strong>{{ $errors->first("tel.$user->id") }}</strong>
        </span>
    @endif
</div>

I'm pulling my hair out , any idea is respected . Thanks for all !

CodePudding user response:

I remember back in 2-3 years I struggled a lot with this too. Here is the answer:

'tel' => 'unique:dtb_users,tel,'. $this->id .''

$this->id is the record you are trying to update. If it doesn't find it like that you can put request()->route()->parameter('paramName');

paramName is the one you declared in the route;

CodePudding user response:

This way is working

$validator = Validator::make($request->all(), [
    'tel.*' => [
        'nullable',
        'min:10',
        'max:12',
        new UserTelUniqueRule($request->all('id', 'tel'))
    ]
]);

In UserTelUniqueRule

<?php

namespace App\Rules;

use App\Models\DtbUsers;
use Illuminate\Contracts\Validation\Rule;

class UserTelUnique implements Rule
{
    /**
     * @param array $input
     */
    protected $input;

    /**
     * Create a new rule instance.
     * @param array $input
     *
     * @return void
     */
    public function __construct($input)
    {
        $this->input = $input;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        foreach ($this->input['id'] as $id) {
            $tel = $this->input['tel'][$id];
            if (is_null($tel)) {
                continue;
            }
            $user = DtbUsers::where('tel', $tel)
                            ->where('id', '!=', $id)
                            ->whereNull('deleted_at')
                            ->first();
            if ($user) {
                return false;
            }
        }

        return true;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return __('validation.unique');
    }
}

CodePudding user response:

I think with an adjustment to how you're naming the input elements of your form, the following should work.

In your blade file, change the value of the name attribute to follow the format:

name="users[{{ $user->id }}][field]"

So;

<input id="tel_{{ $user->id }}" name="users[{{ $user->id }}][tel]"
    
    value="{{ $old['tel'][$user->id] ?? $user->tel }}"
    placeholder="00000000000"
    readonly />

Then in your controller action, update your validation rules to as follows:

$validator = Validator::make($request->all(), [
    'users' => ['required', 'array'],
    'users.*.tel' => [
        'nullable',
        'min:10',
        'max:12',
        Rule::unique('users', 'tel')->ignore('*'),
    ]
]);
  • Related