Could someone please help to understand how to create store method validation in Laravel for the table with the current structure.
Schema::create('product_areas', function (Blueprint $table) {
$table->increments('id');
$table->integer('area_id')->unsigned();
$table->integer('product_id')->unsigned();
});
The area_id
field must be unique only when it has the same product_id
within the same model.
This should be possible:
['id' => 1, 'area_id' => 1, 'product_id' => 1]
['id' => 2, 'area_id'=> 1, 'product_id' => 2]
Where this should throw an error:
['id' => 1, 'area_id' => 1, 'product_id' => 1]
['id' => 2, 'area_id'=> 1, 'product_id' => 1]
I have read the documentation but have not found similar scenario. I have very little idea of how this could be implemented.
Thank you all in advance.
You can conditionally add a validation rule:
$v = Validator::make($data, [
'area_id' => 'required|integer',
'product_id' => 'required|integer',
]);
$v->sometimes('area_id', 'unique:product_areas', function ($input) {
$products = \App\Product::where('id', $input->product_id)->count();
return $products > 0;
});
The above logic will only apply the rule for area_id
when the product_id
returns at least one entry from the database. Here's the relevant documentation. You can also add a new validation rule, but I think the above may suffice in your case.
I think I found the solution, but the solution was that good because I would have to make the additional query on each validation. Here is the solution I came up with:
$v = Validator::make($request->all(), [
'area_id' => [
'required',
Rule::unique('product_areas')->where(function($query) use($request){
return $query->where('product_id', $request->get('product_id'))->get()->count() === 0;
})]
], $this->messages);
$v->validate();
Then after talking to Ben Johnson @cbj4074 and @UncertaintyP on https://gitter.im laravel's channel, they advised me to create unique index containing both columns then try insertion and when it caught exception I could respond with a validation erorr. This was the solution I eventually used.
The composite key which Tim Lewis suggested was also an option but it would not allow identical keys in either columns, so [product_id=>1, area_id=>2] and [product_id=>2,area_id2]
would throw an exception in case of any of the columns would have identical values.
In order to create unique keys I used $table->unique(['product_id', 'area_id'])
schema in migration.