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('*'),
]
]);