Laravel ignore unique validation on update - laravel

I have a Model which contains many foreign keys. One of those foreign keys must be a unique value.
My validation rules are the following ones:
$data['rules'] = [
'address' => 'required|string',
'buyer_id' => 'required|exists:buyers,id',
'buyer_name' => 'required|string',
'date' => 'required|date',
'email' => 'required|email',
'identification_photo' => 'required|string',
'invoice' => 'string|required',
'middleman_id' => 'nullable|exists:middlemen,id',
'price' => 'required|numeric|between:1,99999999999999999999999999.9999',
'property_id' => 'required|exists:properties,id|unique:reservations,property_id',
'purchase_receipt' => 'required|string',
'rfc' => array(
'required',
'regex:/^([A-Z,Ñ,&]{3,4}([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|1[0-9]|2[0-9]|3[0-1])[A-Z|\d]{3})$/'
),
'tier_id' => 'nullable|exists:tiers,id',
'user_id' => 'required|exists:users,id',
];
The one that I have trouble is property_id. This must be unique in the current table which is reservations.
In order to ignore that validation when I make an update, I'm adding this line of code before calling the Validator:
$book['rules']['property_id'] .= ",{$item->property_id}";
And when I do a Log::info of all my rules, I got the following line: 'property_id' => 'required|exists:properties,id|unique:reservations,property_id,4',
But I keep receiving the error. Am I doing something wrong?

The error is on this line:
$book['rules']['property_id'] .= ",{$item->property_id}";
Instead of passing the id of the foreign key you want to ignore, you have to give the current model ID in order to ignore that validation for a specific item.
$book['rules']['property_id'] .= ",{$item->id}";
With this you tell that for your Model with id = x, ignore that specific validation. To understand it in a better way, you are telling that for this validation, ignore the validation of the property only for the record with id equals to the $item->id.

I think the line of code you are looking for is
'property_id' => 'required|exists:properties,id|unique:reservations,property_id,'.$request->id',
This ignores the current row you are updating while also validating your property_id

Related

Array Validation: unique validation on multiple columns

I am trying to check unique validation on three columns employee_id,designation_id,station_id but the data are coming as an array which is making my situation unique and different from other SO questions/answers. I already checked few question like below: checks unique validation on multiple columns
But in my case, I can't get the value as they are inside an array. I also tried to implement Custom Rule or Request but in vain. For all the attempts, I am failing to get the field value such as $request->employee_id as they are inside an array for my case. May be I'm not trying it right.
Controller Code:
$this->validate($request, [
'posting.*.employee_id' => 'required,unique: // what to do here ??',
'posting.*.designation_id' => 'required',
'posting.*.station_id' => 'required',
'posting.*.from_date' => 'required|date',
]);
I am trying to validate uniqueness for both create and update (along with ignore $this->id facility) but don't know how to implement it here for array. It would be no problem if there was no array. Any help/suggestion/guide is much appreciated. Thanks in advance.
You can do this by creating a rule i.e UniquePosting so your controller code would look like
$this->validate($request, [
'posting' => ['required'],
'posting.*' => ['required', new UniquePosting()],
'posting.*.employee_id' => 'required',
'posting.*.designation_id' => 'required',
'posting.*.station_id' => 'required',
'posting.*.from_date' => 'required|date',
]);
Now inside your UniquePosting rule passes function will look like
public function passes($attribute, $value) {
$exists = Posting::where(['employee_id' => $value['employee_id'], 'designation_id' => $value['designation_id'],'station_id' => $value['station_id')->exists();
return !$exists;
}
Add any change if needed, overall that's the concept for testing uniqueness of the whole array.

Laravel unique validation Ignore Rule for update

I have a name field on my Client model which must be unique. For the store method I have the following rules:
array (
'token' => 'string|max:250',
'directory' => 'max:250',
'name' => 'required|string|max:250|unique:clients',
)
For the update method, I have amended this ruleset to ignore the current ID to avoid a duplicate being identified:
$rules['name'] = $rules['name'] . ',id,' . $id;
This produces the following ruleset (for record ID 105):
array (
'token' => 'string|max:250',
'directory' => 'max:250',
'name' => 'required|string|max:250|unique:clients,id,105',
)
When the update method is executed, the The name has already been taken. response is returned during the validation.
I realise this is a well-discussed topic, but believe I am conforming to the correct approach. Can someone point out the error in my logic, please?
Note: This is running on Laravel 5.8.
array(
'token' => 'string|max:250',
'directory' => 'max:250',
'name' => [
'required', 'string', 'max:250',
\Illuminate\Validation\Rule::unique(Client::class, 'email')->ignore($this->id)
]
)

Update a 1 Row 1 Column with Multiple Values

i've some problem with my code.
$id = DB::table('sn_project_details')->insertGetId([
'emp_name' => $request->emp_name,
'emp_id' => $request->emp_id,
'department' => $request->department,
'submit_date' => $request->submit_date,
'total_amount' => $request->total_amount,
'project_tittle' => $request->project_tittle,
'project_desc' => $request->project_desc,
'scope' => $request->scope,
'file' => $request->file
]);
//Update Table
\DB::table('sn_project_details')
->where('project_id', $id)
->update(['doc_ref' => "ID_",$request->scope,"_",$id]);
return redirect('/user')
I want to update column doc_ref with example value ID_Scope_220,
ID_ its fixed value. Scope from textbox scope. 220 from #emp_id.
but when i execute this code, update query not working properly.
can someone help? thx
use dot instead of comma
->update(['doc_ref' => "ID_".$request->scope."_".$emp_id]);

Why are multiple rows ('versions') saved with eloquent, when I only edit one

I use a versioning system to save multiple versions of a 'minor' (a model in my application). It contains quite a few fields, like name, goals, requirements, subject and many more. When I save a new version, or 'version 2', using eloquent, it also changes the other version.
I have tried multiple ways of saving the minor, like requesting the first one and updating it like below, or changing each individual item one-by-one.
Minor::limit(1)
->where("id", $id)
->where('version', $_POST['version'])
->first()
->update([
'name' => $_POST['name'],
'ects' => floatval($_POST['ects']),
'contact_hours' => intval($_POST['contact_hours']),
'education_type' => $_POST['education_type'],
'language' => $_POST['language'],
'subject' => Input::get('subject'),
'goals' => Input::get('goals'),
'requirements' => Input::get('requirements'),
]);
It should only save the selected version, but instead, it overwrites all versions of the minor with the same ID and saves them to the database.
How can I prevent this, or does anyone have an idea on how to fix this?
You can try using updateOrCreate method:
Minor::updateOrCreate([
'id' => $id,
'version' => $_POST['version']
],[
'name' => $_POST['name'],
'ects' => floatval($_POST['ects']),
'contact_hours' => intval($_POST['contact_hours']),
'education_type' => $_POST['education_type'],
'language' => $_POST['language'],
'subject' => Input::get('subject'),
'goals' => Input::get('goals'),
'requirements' => Input::get('requirements'),
]);
I still don't know why this happened or how to fix it using the same method. I have however found a way around it. I now update and save the minor with the ->update([...]) method build into eloquent.
Minor::where([["id", "139858"], ["version", Input::get('version')]])
->update([
'name' => Input::get('name'),
'ects' => Input::get('ects'),
'contact_hours' => Input::get('contact_hours'),
'education_type' => Input::get('education_type'),
'language' => Input::get('language'),
'subject' => Input::get('subject'),
'requirements' => Input::get('requirements'),
'goals' => Input::get('goals')
]);
This doesn't seem to alter the other versions. This is the only way I found to make it work, you can't make a variable of the object, change values and then save it. That would overwrite the other versions.

Optimize ApiResource

I'm having some problems when returning ApiResources because I can't figure out how to avoid overloading relationships.
In my UserResource, for example, I have:
<?php
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'role_id' => $this->role_id,
'role' => new RoleResource($this->whenLoaded('role')),
'group_ids' => $this->groups->pluck('id')->toArray(), // here are the problems
'groups' => GroupResource::collection($this->whenLoaded('groups')),
];
When loading single relationship id, all is ok, because $this->role_id is a property that is already in the Model. When using $this->whenLoaded('role') It will load the relationship conditionally, that's great!
The Problem: When loading many-to-many relationships, I can't set this 'conditional' eager load.
When I place:
'groups' => GroupResource::collection($this->whenLoaded('groups'))
It will load the ManyToMany Relation conditionally, cool!
BUT I would like to have array of ids with:
'group_ids' => $this->groups->pluck('id')->toArray()
However, this will execute the relation load ALWAYS

Resources