Laravel uniqueness validation of hasMany - validation

I need to validate with the rule unique all code of the list of children before update, I know how to do it for the parent:
$parent = Parent::find($id);
$childrens = $parent->childrens;
'code' => ['required', Rule::unique('parents', 'code')->ignore($parent->id)],
'childrens.*.code' => ['required', Rule::unique('childrens', 'code')],
There is any easy way to get the current IDs of children to ignore them like I did in the parent? Or any idea to allow update of the child?

The solution for hasMany relation in update is:
for ($i = 0; $i < $childrens->count(); $i++) {
$rules['childrens.' . $i . '.code'] = ['required', Rule::unique('childrens', 'code')->ignore($childrens[$i]['id'])];
}

Related

Laravel unique validation of two columns when validating against an array

I can validate two table columns for uniqueness by customizing the where query like this.
'email' => [
'required',
Rule::unique('users')->where(function ($query) {
return $query->where('account_id', $this->request('account_id'));
})
]
How would i do a similar thing when validating an array of data?
'email.*' => [
'required',
Rule::unique('users')->where(function ($query) {
// How can i customize the query per array element?
})
]
2022 Update
Laravel 9 now has functionality for this exact problem.
https://laravel.com/docs/9.x/validation#accessing-nested-array-data
Ended up with the following, though i was hoping there was a way to access the current index of the currently validated array element from within the function params themself.
$i = 0;
'email.*' => [
'required',
Rule::unique('users')->where(function ($query) use (&$i) {
return $query->where('account_id', $this->request('account_id')[$i]);
$i += 1;
})
]

Best way to bulk create models within Laravel?

I am creating a feature which involves creating voucher codes for discounts. I contain an input which the user can fill out with the specific amount they want.
When it hits the store method say if the user has entered 15 vouchers how would you create that many model records in one go?
From looking at the laravel documentation the only thing i've seen is using factories so i've attempted this below.
public function storeCodes(Request $request, VoucherGroup $voucherGroup)
{
VoucherCode::create([
'code' => $this->generateUniqueCode(),
'group_id' => $voucherGroup->id,
'used' => 0
]);
session()->flash('success', 'successfully created codes.');
return back();
}
private function generateUniqueCode()
{
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersNumber = strlen($characters);
$code = '';
while (strlen($code) < 6) {
$position = rand(0, $charactersNumber - 1);
$character = $characters[$position];
$code = $code . $character;
}
if (VoucherCode::where('code', $code)->exists()) {
dd('lol');
$this->generateUniqueCode();
}
return $code;
}
Input
<x-inputs.input size="6" type="number" name="voucher_amount" required>How many Voucher codes do you want
to
generate?
</x-inputs.input>
The problem is it creates the models but the code returns the same code for each model.
How would I create 15 models in one call with unique code fields?
The for loop below solved this for me. It was originally posted by someone but its been deleted recently so ill answer the question below but thanks to whoever provided it!
$newVouchers = [];
for ($i = 0; $i < $request->voucher_amount; $i++) {
$newVouchers[] = VoucherCode::create([
'code' => $this->generateUniqueCode(),
'group_id' => $voucherGroup->id,
'used' => 0
]);
}
You can try it shortly
do {
//generate unique code
$uniqueCode = strtoupper(substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, 15));
} while (VoucherCode::where('code', $uniqueCode)->exists());
VoucherCode::create([
'code' => $uniqueCode,
'group_id' => $voucherGroup->id,
'used' => 0
]);
session()->flash('success', 'successfully created codes.');
return back();
You can use Insert Statements to bulk create models
$vouchers = [];
for ($i = 0; $i < $numberOfVoucher; $i++) {
$vouchers[] = [
'code' => $this->generateUniqueCode(),
'group_id' => $voucherGroup->id,
'used' => 0
];
}
DB::table('users')->insert($vouchers);

Laravel: How to save into two tables , but, the id of the first will be saved into the second as foreign id

I have two tables in laravel, the student and parent, the idea is upon creating a student account, the parent account is auto-generated. However, there are chances, a parent can have two children or more in a school. zo, before saving into the database, it should query the parent table to see if the parent exists, if it exists, fetch the id and save it into the student table, BUT, if the parent does not exist, save the parent into the parent table, thereafter fetch the parent id and save into student table......
sadly, the parent ID is always zero in student id
so far,
$parentt = Parentt::where('phone', '=', $request->parentMobileNumber)->first();
if ($parentt === '') {
$parenttInstance = new Parentt();
$parenttInstance->name = $request->parentName;
$parenttInstance->phone = $request->parentMobileNumber;
$parenttInstance->password = bcrypt($request->password);
$parenttInstance->save();
$parentID = $parenttInstance->id;
}else {
$parentID = $parentt->pluck('id');
}
}
$data = array(
'first_name' => $request->firstName,
'surname' => $request->lastName,
'phone' => $request->phone,
'email' => $request->email,
'gender' => $request->gender,
'parent_id' => $parentID
'password' => Hash::make($request->firstName)
);
Student::create($data);
return back()->with('success', 'Student successfully added.');
pluck returns Enumerable, you need the actual value, try:
$parentID = $parentt->id;
We can use the pluck() method when there are a collection of objects but in your case, the query returns one object, hence you can directly call the id as #Script47 mentioned.
$parentID = $parentt->id;

Update multiple rows in Database Table

I want to update multiple rows. Here is my controller file:
$ids = [$request->get('com_id')];
$name = [$request->get('com_name')];
$stat = [$request->get('com_status')];
$now = Carbon::now();
$count = count($ids);
$thiss=$request->validate(
['com_name' => 'required',
'com_status' => 'required'
]);
// $i=0;
for ($i=0; $i <$count ; $i++) {
$companies = companies::find($ids[$i][0]);
companies::where('id',$ids[$i][0])
->update(['company_name' => $name[$i][0],
'status' => $stat[$i][0]
]);
but in my code, Just the 1st row is being updated. what can I do for updating multiple rows with array index number?
You are trying to access the id from a two dimensional array and you are initializing the $ids variable like $ids = [$request->get('com_id')];. Please first check that you have all the ids in the $ids array. if that is alright then any of the following code should work,
// #1
companies::where('id', $ids[$i][0])
->update([
'company_name' => $name[$i][0],
'status' => $stat[$i][0]
]);
// #2
$company = companies::find($ids[$i][0]);
$company->company_name = $name[$i][0];
$company->status = $stat[$i][0];
$company->save();
You should follow the doc to for updating, please look into the https://laravel.com/docs/5.6/eloquent#updates and you may find more details.

How to add unique validation on combination of firstname and lastname in laravel5?

I need to validate user table in which not repeated combination of (firstname and lastname). for example:- firstname=dc lastname=patel already exist in table. i need to prevent same entry next time.
Finally I have perfect solution for this.
$validationRule = ['first_name' => 'required','last_name'=>'required'];
$validationMsg = ['first_name.required' => 'First Name is required', 'last_name.required' => 'Last Name is required'];
$validation = Validator::make(['first_name' => $firstName, 'last_name' => $lastName], $validationRule, $validationMsg);
$validation->after(function ($validation) use ($firstName, $lastName) {
$checkName = User::where('first_name', $firstName)->where('last_name', $lastName)->get();
if (count($checkName) > 0) {
$validation->errors()->add('first_name', 'User already exists, please enter another user.');
}
});
if ($validation->fails()) {
foreach ($validation->errors()->all() as $error) {
$message = $error;
}
return response(\Helpers::makeAjaxResponse(false, $message));
} else {
//Save record code here
}
You can use something simular to composite UNIQUE key in table if database provide this possibility.
http://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html
with using laravel unique validation rule
how can you allow users with same lastname but not firstname for registeration?
unique.firstname
First check records count with the given firstname and lastname.
If the count is '0' save the record or else show message.
Here is some code hint
$users = DB::table('users')
->where(['firstname' => 'dc', 'lastname' => 'patel'])
->count();
if($users === 0) {
// save the record.
} else {
// Show message
}
Since Laravel 5.5 you can use elegant Rule class like:
use Illuminate\Validation\Rule;
// ...
$firstNameUniqueRule = Rule::unique('users')->where('last_name', request()->get('last_name', ''));
$rules = [
'first_name' => ['required', $firstNameUniqueRule],
'last_name' => 'required',
];

Resources