我一直在网上,为此苦苦挣扎了大约 2 个小时。
我有一个用户模型,一个运行模型和一个时间模型。
在现实世界中,用户处于竞赛中,并将他们的时间与USER_id和RUN_id一起输入到数据库中。
对于每个RUN_id,用户应该只能在 TIMES 表中拥有一行 - 如果这有意义的话!
这是我需要在控制器级别管理的内容吗?或者我可以设置关系以确保此样式的重复条目无法进入数据库?
目前的数据库结构:
用户:
名字
运行:
名字
次:
时间
user_id
run_id
模型:
用户:
public function times()
{
return $this->hasMany(Time::class);
}
跑:
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Run extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function times()
{
return $this->hasMany(Time::class);
}
}
时间:
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Time extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function run()
{
return $this->belongsTo(Run::class);
}
}
您可以在times
表上添加唯一键约束,以强制实施user_id和run_id的唯一组合
$table->unique(['user_id, 'run_id']);
为了在应用程序级别验证唯一性,我们还可以在表单验证中添加约束。假设您在创建新时间的请求中同时传递user_id和run_id,则可以将以下内容添加到表单请求中
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'user_id' => Rule::unique('times')->where('run_id', $this->input('run_id'))
];
}
public function messages()
{
return [
'user_id.unique' => 'A user may only have 1 time entry per Run'
];
}
这将强制user_id在times
表中是唯一的,并按该运行 ID 进行筛选。messages 函数还会返回更有用的错误消息,因为在这种情况下,"user_id必须是唯一的"是没有帮助的。
这个答案应该补充公认的答案。您仍应将 user_id,run_id 对定义为唯一键。 但是,在您的情况下,用户和运行与作为数据透视表times
具有 N-N 关系。您应该这样编码。
用户
public function runs()
{
return $this->belongsToMany(Run::class, 'times')->withPivot('time');;
}
跑:
public function users()
{
return $this->belongsToMany(User::class, 'times')->withPivot('time');
}
然后,您可以按以下方式检索它们:
$runs = User::find($userId)->runs; // Collection of all runs a user participated in
// $runs[X]->pivot->time has the time
您可以查看文档以获取更多信息