这是一个棘手的问题,标题可能有点混乱,所以我会尽力解释。
基本上,我正在创建一个Recipe应用程序,用户可以在其中创建列表并添加食谱。
我希望列表中每个配方只能有一个实例,因此,例如,如果我将配方10添加到列表编号1中,我不希望用户能够将配方10再添加到列表1中。
现在,我只使用验证来检查食谱表中是否已经存在meal_id(食谱的id(,但通过验证,我只能将每个食谱添加到一个列表中。
$this->validate($request, [
'name' => 'required',
'meal_id' => 'required|unique:recipes,meal_id',
'list_id' => 'required'
]);
我的关系很简单,一个食谱有一个食谱列表,一个菜谱列表有很多食谱,但我很确定改变它不会是解决问题的办法。
配方型号
class Recipe extends Model
{
use HasFactory;
protected $fillable = [
'name',
'meal_id',
'list_id'
];
public function lists()
{
return $this->hasOne(RecipeList::class);
}
}
RecipeList型号
class RecipeList extends Model
{
use HasFactory;
protected $fillable = [
'name',
'user_id'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function recipes()
{
return $this->hasMany(Recipe::class);
}
}
配方表
public function up()
{
Schema::create('recipes', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('meal_id');
$table->unsignedBigInteger('list_id');
$table->timestamps();
});
}
然而,也许我需要设置某种形式的透视表?
有人对通过验证实现我想要的东西的聪明方法有什么想法吗?或者有其他想法吗?
您可以使用Rule
并创建自定义验证来添加条件
这里我假设您的条件是在list_id
和meal_id
上添加一个唯一的限制
$this->validate($request, [
'name' => 'required',
'list_id' => 'required',
'meal_id' => [
required,
unique:recipes,meal_id,
IlluminateValidationRule::unique('recipes')->where(function($query) use ($request){
$query->where('list_id', $request->list_id)
->where('meal_id', $request->meal_id);
}),
],
]);
使用firstOrCreate()
。点击此处阅读更多信息:https://laravel.com/docs/8.x/eloquent#retrieving-或创建模型
示例:
$recipeData = $request->validate([
'name' => 'required',
'meal_id' => 'required',
'list_id' => 'required'
]);
$recipe = Recipe::firstOrCreate($recipeData);
这将使用您的3个字段,name
、meal_id
&list_id
,并且如果它还不存在,则将选择一个或创建它。
或者,您可以执行查询以检查它是否存在。如果您想向用户返回一条错误/消息,说明新的是重复的。
$existingRecipe = Recipe::where([
'meal_id' => $recipeData['meal_id'],
'list_id' => $recipeData['list_id'],
'name' => $recipeData['name']])
->first();
if(!is_null($existingRecipe)) {
//return exists
}
当然,使用规则会更有效率,这取决于您希望UI表达什么。
参见BABAK ASHRAFI的回答