仅当兄弟字段相同时,Laravel唯一值验证

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.