Laravel validation: exists two column same row - php

Is there a way of referencing another field when specifying the exists validation rule in Laravel?
My request :
public function rules()
{
return [
'numero_de_somme' => 'unique:personnels,numero_de_somme|exists:fonctionnaire,num_somme',
'cin' => 'unique:personnels,cin|exists:fonctionnaire,cin',
];
}
in my validation rules I want to be able to make sure that:
num_somme exists within the fonctionnaire table
cin exists within the fonctionnaire table and cin input must be
on the same row of the num_somme
num_somme : 12345 cin : s89745
num_somme : 78945 cin : U10125
Explaining : for example
1st scenario if the input num_somme = 12345 and cin = U10125 the validation must fail
2nd scenario if the input num_somme = 12345 and cin = s89745 the validation must success
I hope this makes sense.
Thank you

You can simply use this:
'request_input' => exists:table,col,alternative_col_1,alternative_val_1,alternative_col_2,alternative_val_2, ...'
The SQL query is like below:
select count(*) as aggregate from `table` where `id` = [request_input] and `alternative_col1` = "alternative_val1" and `alternative_col2` = "alternative_val2"

I came across the same need today and I think I have a solution using the validation Rule class: Rule example.
Here is my scenario: I have an email verifications table and I want to ensure that a passed machine code and activation code exist on the same row.
Be sure to include use Illuminate\Validation\Rule;
$activationCode = $request->activation_code;
$rules = [
'mc' => [
'required',
Rule::exists('email_verifications', 'machineCode')
->where(function ($query) use ($activationCode) {
$query->where('activationCode', $activationCode);
}),
],
'activation_code' => 'required|integer|min:5',
'operating_system' => 'required|alpha_num|max:45'
];
The first argument in the exists method is the table and the second is the custom column name I'm using for the 'mc' field. I pass the second column I want to check using the 'use' keyword and then use that field in a a where clause.

You can achieve validating multipe columns by using Rule.
Include :
use Illuminate\Validation\Rule;
use Validator;
$AdminId = $request->AdminId;
$Validate = Validator::make($request->all(),[
'TaxId' => [ 'required', Rule::exists('tax','id')
->where(function ($query) use ($AdminId) {
$query->where('u_id', $AdminId);
})],
]);
if($Validate->fails())
{`Your ERROR HERE`}
else
{`SUCCESS`}
Here in my example I'm checking u_id and Id which is in same row and 2 columns.
Explaining : for example
My DB HAS 2 ROWS IN tax TABLE
id = 1 , u_id = 1, tax = "GST" , value -> 8
id = 2 , u_id = 2, tax = "GST" , value -> 5
1st scenario if the input id = 2 and u_id = 1 the validation must fail because this row belongs to u_id = 2.
2nd scenario if the input id = 2 and u_id = 2 the validation must success

i managed to solve it using the most simple method
for numero_de_somme
'numero_de_somme' => 'unique:personnels,numero_de_somme|exists:fonctionnaire,num_somme,cin,'.Request::get('cin'),
for cin
'cin' => 'unique:personnels,cin|exists:fonctionnaire,cin',
PS . don't forget to call use Illuminate\Http\Request;

if (is_numeric($request->get('emailOrphone'))){
$request->validate([
'emailOrphone'=>'exists:users,phone',
],
[
'emailOrphone.exists'=>'phone is invalid.'
]);
}else{
$request->validate([
'emailOrphone'=>'exists:users,email',
],
[
'emailOrphone.exists'=>'email is invalid.''
]);
}

Related

Laravel select columns and then group column value by date

I'm trying to get what should seem like a simple SQL query to work in my Laravel project, I've got a front-end web application that allows a user to pull data from various pre-defined tables and a selectable list of columns.
This works fine if I don't attempt to select and groupBy together, equally, I need someway of grouping baed on whether the user wants to group data by a day, or a month for instance.
My POST request looks like, where each array item inside the parent array is a table:
[
[
table: 'my_table',
columns: ['event_category', 'event_action', 'event_count', 'created_at'] ...
filterBy: [
['event_category', 'my category'],
['event_action', 'some action']
],
orderBy: {
field: 'created_at',
direction: 'desc'
}
]
]
Each row in my_table contains an event_count column, which contains a number, so if there's 5 rows for a particular day with different event_count numbers, I need to add up all of those event_count entries and group them by that day
Here's my function and query:
public function findDataFromSources(Request $request)
{
$request_data = $request->all();
$realData = [
'size' => 0,
'results' => [],
'filtered' => []
];
foreach ($request_data as $key => $findable) {
// NOTE: this works for retrieving data that isn't grouped
// $res = DB::table($findable['table'])
// ->select($findable['columns'])
// ->where($findable['filterBy'])
// ->orderBy($findable['orderBy']['field'], $findable['orderBy']['direction'])
// ->take(20)
// ->get();
// TODO: this isn't grouping for some reason...
$res = DB::table($findable['table'])
->select($findable['columns'], DB::raw('sum(event_count) as total_events'))
->groupBy('created_at')
->orderBy($findable['orderBy']['field'], $findable['orderBy']['direction'])
->get();
$realData['size'] += count($res);
array_push($realData['results'], $res);
}
$data = [
'success' => true,
'message' => 'Your chosen data sources and fields',
'sources' => $realData
];
}
What am I missing? The error I'm getting is:
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column
->select($findable['columns']
You cannot SELECT fields/columns that are not in GROUP BY without aggregate function and your $findable['columns'] probably contain fields that are not in GROUP BY.
You can use ANY_VALUE() like #RobbinBenard commented for example
->select(DB::raw('ANY_VALUE(' .$findable['columns'][0] .')'))
You can loop through the columns and use addSelect() to add those columns.
$query = DB::table($findable['table'])
->select(DB::raw('sum(event_count) as total_events'));
foreach($findable['columns'] as $column) {
$query->addSelect(DB::raw('ANY_VALUE(' .$column .')'));
}
$res = $query->groupBy('created_at')
->orderBy($findable['orderBy']['field'], $findable['orderBy']['direction'])
->get();

Laravel Validate if there is already a record with similar combination of two columns

For example, I have an auction where Users can bid on items.
When a user creates a new bid I want to be sure that this user didn't bid on this item before.
The BID table structure is id, item_id, user_id, price. So basically I need to check if there is a record that has same item_id and same user_id at the same time.
Is there any way to do this using Laravels Validator?
$validator = Validator::make($request->all(), [
'item_id' => 'unique:item_id,user_id,NULL,id,'. auth()->user()->id,
'price' => 'required|integer'
]);
The error I have:
Undefined offset: 1
According to Laravel docs:
[
'item_id' => 'unique:bids,item_id,null,id,user_id,' . auth()->id(),
]
Create a model for Users table.
Now,
$itemIds= User:: where ('user_id',$userId)->pluck('item_Id');
foreach($itemIds as $itemId){
if ($itemId == $newItemId) {
// write code if item id is already present
}
else {
// write code if item id is not present
}
}
you can use laravel unique validation as
'user_id' => 'unique:item_id,user_id,NULL,id,'.$user->id

Make custom Error validation rule

I'm trying to store student info in database id, name with course_1, course_2 from a form.
Same student can't register for same course again.
Students Table
id name
1 X
2 Y
Courses Table
id course_name
1 A
2 B
Student_courses Table
student_id courses_id
1 1
2 1
2 2
Student controller like this :
public function studentRegistration(Request $request)
{
$student = new Student();
$student->name = $request->Input(['student_name']);
$student->save();
$courses = array(
$request->Input(['course_1']),
$request->Input(['course_2']),
$request->Input(['course_3'])
);
foreach ($courses as $course)
{
$studentCourse = new StudentCourse();
$studentCourse->student_id = $student->id;
$studentCourse->course_id = $course;
$studentCourse->save();
}
}
How to make this custom validation with Laravel so same student can't take same course again?
Could you use an existing rule?
Validation rules:
'course_1' => 'different:course_2,course_3|...',
'course_2' => 'different:course_3|...',
I am not sure how exact the actual problem is to the example. If these fields are more dynamic than that, then a custom rule would make sense.
That is just for validating the input to be unique values for those fields. To check against the database is where the unique rule can come in:
'course_1' => [..., $uniqueRule = Rule::unique('student_courses', 'course_id')->where('student_id', $whoEverTheStudentToCheckAgainstIs)],
'course_2' => [..., $uniqueRule],
'course_3' => [$uniqueRule],
Could hide that behind a custom rule if you really needed to.

Is there a way to check if a couple of inputs are unique in laravel 5.2?

update
What I have is a table with these columns:
- ID
- production_year
- type
If the type is already present in the table with the value the user wants to pass, check if production_year is already present too, but fail the validation ONLY if these values are present in the same record. Otherwise let the user to store this record.
I'm trying to check the uniqueness of a couple of fields in the same record...
I've seen the documentation about the conditional validation, but I didn't quite find the answer there.
the code
public function rules()
{
return [
// I'd like to check the uniqueness of both of them. In the same record
'production_y' => 'required|unique',
'fk_type' => 'required|unique',
];
}
Any idea? Thanks!
Laravel 5.3 Update:
Now, you can generate the same rule fluently using the Rule (\Illuminate\Validation\Rule) class.
NULL,id part of the string way is no more required. See:
public function rules()
{
$type = $this->get('fk_type');
return [
'production_y' => [
'required',
Rule::unique('your_table', 'production_year')->where(function($query) {
$query->where('type', $type);
}),
],
];
}
Original Answer
Can't test right now, can you try:
public function rules()
{
$type = $this->get('fk_type');
return [
'production_y' => "required|unique:your_table,production_year,NULL,id,type,{$type}",
// ...
];
}
Explaination:
unique:your_table Set the table for the unique check.
,production_year This matches with production_y.
,NULL,id check all the records.
3.1. if you use like {$id},id it will check uniqueness except the record with the {$id},
,type,{$type} and the type should be {$type}
That will produce sth. like (not exact query, just to express the idea):
select count(*) from your_table where production_year = $product_y and where type = $type and where id <> null
if someone cames from laravel 8, i tried this and it worked !!
for me i need to check the uniqueness of (category_id,subcategory_id) which mean you can find (1,2),(1,3),(2,1),(2,3) but you cant find similar couple !!
'category' => "required|unique:tickets,category_id,NULL,id,subcategory_id,{$request->input('subcategory')}"

Laravel 5 multiple table unique validation

For example, I have 2 tables : sites1 and sites2
I need to check that field url which is comes from my html form is unique.
Here my validation rule :
public function rules()
{
return [
'url' => unique:sites1|unique:sites2'
];
}
Unfortunately, this rule applies only for sites2 table. Is there any possible ways to validate both tables?
Your validation rule seems ok. Just make sure that both sites1 and sites2 table has field name url and both in same database.
Your unique:sites1 rule will be translated into SQL
select count(*) as aggregate from `sites1` where `url` = ?
While unique:sites2 rule will be translated into SQL
select count(*) as aggregate from `sites2` where `url` = ?
See if first SQL does return result. Long URL may result non unique if used with limited index length. It may be better if you could store hash value of URL so you can compare url just by using hash.
No need to maintain the same name in two different tables
In laravel 4.2
Validator::make(Input::all, [
'url' => 'unique:site1,your_column_name|unique:site2:your_column_name_2'
]);
Laravel 5.*:
$this->validate($request,[
'url' => 'unique:site1,your_column_name|unique:site2:your_column_name_2'
]);
Hopefully it's working fine.
In the above answer i think you can't use custom error message, you can do in another way just copy the filed in another field for the two checks.
public function validator(array $data)
{
$data = ['url2' => $data['email']];
$rules = [
'url' => 'unique:sites1',
'url2' => 'unique:sites2',
];
$messages = [
'url.unique' => 'url unique in site 1',
'url2.unique' => 'url unique in site 2',
];
return $validator = Validator::make($data, $rules, $messages);
}
if ($validator->fails()) {
if(!empty($validator->errors()->get('url2'))) {
$validator->errors()->add("url", 'url unique in site 2');
}
}

Categories