Reputation:
Is there a way to build a validation in Laravel which checks if two columns together are unique in a table?
So for example if there is [(A, B)] in my table, then the input (A, A) or (B, B) should pass the validation but (A, B) again have to fail.
For example like this:
DB::table('mytable')
->where([
['col1', $item->col1],
['col2', $item->col2]
])
->exists();
But I want to do it within a validation, so something simular to this:
public function validate() {
return Validator::make($this->attributes, [
'col1|col2' => 'unique:mytable',
//....
])->errors();
}
Upvotes: 2
Views: 1956
Reputation: 3466
If you are looking for validation of uniqueness of composite indexes (multiple columns), this is not possible unless you create a custom validation rule.
You can create a custom validation rule, see https://laravel.com/docs/validation#custom-validation-rules
// Example:
// 'col1' => 'unique_with:table,col2,col3,col4,etc'
// 'col2' => doesn't need to check uniqueness again, because we did it for col1
Validator::extend('unique_with', function ($attribute, $value, $parameters, $validator) {
$request = request()->all();
// $table is always the first parameter
// You can extend it to use dots in order to specify: connection.database.table
$table = array_shift($parameters);
// Add current column to the $clauses array
$clauses = [
$attribute => $value,
];
// Add the rest
foreach ($parameters as $column) {
if (isset($request[$column])) {
$clauses[$column] = $request[$column];
}
}
// Query for existence.
return ! DB::table($table)
->where($clauses)
->exists();
});
place that code in the boot()
method of a service provider, you can use App\Http\Providers\AppServiceProvider.php
I didn't test it, but it should help you to go forward and make the necessary adjustments.
Upvotes: 1
Reputation: 50787
I think what you're looking for is to require them if either exists, but make sure both are unique. This should work for you:
'col1' => 'unique:mytable|required_with:col2',
'col2' => 'unique:mytable|required_with:col1'
Upvotes: 0