How to make Laravel unique validation work on an input array? - php

UpdateEntityRequest.php:
'phones' => 'sometimes|nullable|array',
'phones.*.id' => 'sometimes|required|integer|distinct|exists:entity_phones,id,entity_id,'.$this->id,
'phones.*.number' => 'required|alpha_num|max:255|distinct|unique:entity_phones,number,'.$this->id.',entity_id',
entity_phones table:
id, number, entity_id.
unique constraint: (number, entity_id)
EntityRepository.php:
foreach ($attributes['phones'] as $phone) {
if (isset($phone['id'])) {
$entity->phones()->updateOrCreate([
'id' => $phone['id'],
'entity_id' => $entity->id
], $phone);
} else {
$entity->phones()->create($phone);
}
}
My entity can have more than phone associated, but not a repeated number. My intention is to check the unique (entity_id, number) in the UpdateEntityRequest.php so:
If the phone object comes without an id, it should check that the combination of number, entity_id doesn't exists. But the number can exist with other entity_id.
If the request comes with an id, it should check that the combination of number, entity_id doesn't exists only in other ids, but ignore the given id.
I'm having trouble witht the Laravel Unique rule validating only when i want it to make the validation. Any ideas how could I make this solution would be appreciated.

If you need to ignore a given ID during the unique check try using the Rule class to fluently define the rule.
use Illuminate\Validation\Rule;
Validator::make($request_data, [
'number' => [
'required',
'alpha_num', (...all your other rules)
Rule::unique('entity_phones')->ignore($entity_id),
],
]);
You can read more in laravel docs about unique rule in paragraph: Forcing A Unique Rule To Ignore A Given ID.

I ended up doing this:
$phoneIds = $this->input('phones.*.id');
'phones.*.number' =>
[
'required_with:phones',
'alpha_num',
'max:255',
'distinct',
Rule::unique('entity_phones', 'number')
->where('entity_id', $this->id)
->where(function ($query) use ($phoneIds) {
return $query->where('id', '!=', array_shift($phoneIds));
})
],

Related

Laravel 8 unique validation rule doesn't work with user_id

I'm using Laravel 8 and the unique validation rule to ensure that a record remains unique, I'm now trying to extend this so that it's unique per user as well, but when expanding the functionality and using the rule in array form it doesn't seem to validate the user ID and instead gives me a integrity constraint violation.
So I have a table called brands, and this table contains two columns in question: brand and user_id, I need to ensure that when storing a record that the brand is unique against the brand column and that the logged in in user's ID the one making the request, e.g:
Two users can have the same brand, but a single user can't have multiples of the same brand.
$validator = Validator::make($request->all(), [
'brand' => [
'required',
'string',
Rule::unique('brands')->where(function ($query) {
return $query->where('user_id', Auth::id());
})
],
'url' => 'required|string',
'telephone' => 'required|string|min:11|max:11'
]);
I've also tried:
'brand' => 'required|string|unique:brands,brand,user_id,' . Auth::id()
What am I missing?
According to the documentation you have to use the ignore() function:
Rule::unique('users')->ignore($user->id),
on your case:
Rule::unique('brands')->ignore($user->id, 'user_id'),

Unique validation with 2 columns - Laravel 8.x

I've been trying make my validation so that an extension must be unique to it's own company but not to other companies. Here is my DB table:
$table->id();
$table->foreignId('user_id')->constrained();
$table->foreignId('account_id')->constrained()->onDelete('cascade');
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('email');
$table->string('extension');
$table->string('password')->nullable();
$table->string('user_type')->default('user');
$table->timestamps();
$table->unique(['extension', 'account_id'], 'unique_extension');
And my validation rule looks like this:
public function rules()
{
return [
'editExtension.first_name' => 'required|max:255',
'editExtension.last_name' => 'required|max:255|',
'editExtension.email' => ['required', 'email','max:255', Rule::unique('account_users', 'email')->ignore($this->editExtension->id)],
'editExtension.extension' => ['required', 'numeric', Rule::unique('account_users', 'extension', $this->client_id)->ignore($this->editExtension->id)],
'editExtension.password' => 'required|max:255',
'editExtension.user_type' => 'required|in:user,admin',
];
}
But still I got errors saying that the extension number is already taken.
It seems that the Unique rule doesn't accept multiple columns, only one. Is this true?
How can I fix this?
Forcing A Unique Rule To Ignore A Given ID:
UPDATING AN EXISTING RECORD.
"account_users" => Table name.
"account_id", "extension" => The 2 fields to check for uniqueness.
ID of currently edited row here. => The id (primary key) to ignore. (The currently updated/edited table row id.)
Rule::unique("account_users")->where(
function ($query) use ($request) {
return $query->where(
[
["account_id", "=", $request->account_id],
["extension", "=", $request->extension]
]
);
})->ignore(/* ID of currently edited row here. */)
CREATING A NEW RECORD.
Rule::unique("account_users")->where(
function ($query) use ($request) {
return $query->where(
[
["account_id", "=", $request->account_id],
["extension", "=", $request->extension]
]
);
})
Addendum
By default, the unique rule will check the uniqueness of the column
matching the name of the attribute being validated. However, you may
pass a different column name as the second argument to the unique
method:
Rule::unique("account_users", "extension")->where(...)

Laravel validation rule fails when trying to update the same record with no changes

I've got a table called Sides which consists of id, name, side_category_id and some other fields not important at the moment.
I wanted to validate that when creating a new side record, the record doesn't exist already. So, let's say I've got in the database a record such as:
id: 1
name: Salad
side_category_id: 3
If I try to insert a new record with name = 'salad' and side_category_id = 3 then the creation must fail and return an error.
I've achieved this by using the following rule:
$rules = [
'name' => 'required',
'side_category_id' => 'required|exists:side_categories,id|unique:sides,side_category_id,NULL,id,name,' . $this->request->get('name')
]
So far so good. It works as it's supposed to. But now it's returning an error if I want to edit a record and save it without any modifications and this is not my desired outcome.
If I try to update the record with no modifications it should succeed. How can I update my rule to achieve this?
you can use Rule::unique()
for create use like this
$rules = [
'name' => ['required'],
'side_category_id' => ['required',Rule::unique('sides', 'name')->where(function ($query) use($category_id) {
return $query->where('side_category_id', $category_id);
}),Rule::exists('side_categories')]
]
for update
$rules = [
'name' => ['required'],
'side_category_id' => ['required',Rule::unique('sides', 'name')->where(function ($query) use($category_id) {
return $query->where('side_category_id', $category_id);
})->ignore($id),Rule::exists('side_categories')]
]
//$id should be you parameter

Laravel Unique keyword for particular Column

I'm using "unique" keyword for validating unique users for employee_id in controllers, in my database there is column called company_id , while adding new user they will be set us some company_id ,when i add new user for my company employee id will be unique for my company itself , if employee_id is 4 for another company and i'm adding 4 for my company it must accept , it will check only for that particular company only.
$this->validate($request,
[
'name' => 'required',
'emp_id' => 'required|unique:users', (Here how can i check for particular company)
'email' => 'required|unique:users',
'role' => 'required',
]);
can anyone please help me ???
You should use the array syntax here and use a "custom" unique rule:
'emp_id' => [ "required", Rule::unique('users')->where(function ($query) use ($request) {
$query->where('emp_id', $request->emp_id)->where("company_id",$request->company_id);
}) ]
Something like this anyway
If emp_id and company_id is in request
'emp_id' => 'required|unique:users,emp_id|unique:users,company_id',
Check in docs : https://laravel.com/docs/master/validation#rule-unique
I assume emp_id and company_id are present in users table and you are sending in request

Validating a JSON array in Laravel

I have a controller which receives a following POST request:
{
"_token": "csrf token omitted",
"order": [1,2,3,4,5,6,7,8]
}
How can I use validators to ensure that elements in order are unique, and between 1 and 7? I have tried the following:
$this->validate($request, [
'order' => 'required|array',
'order.*' => 'unique|integer|between:1,7'
]);
The first clause is checked, the secound one passes even when the input is invalid.
Using distinct rule:
distinct
When working with arrays, the field under validation must not have any
duplicate values.
In your case, it could look like this:
$this->validate($request, [
'order' => 'required|array',
'order.*' => 'distinct|integer|between:1,7'
]);
The unique validator keyword is for checking a value's duplicates in database.
You should use custom validator for such situations.
See: https://laravel.com/docs/5.1/validation#custom-validation-rules

Categories