laravel - 在 Laravel 中根据外键使列唯一
问题描述
我有两个模型EventLocation
和EventDepartment
. 模型及关系如下图所示:
class EventLocation extends Model
{
public function event_departments()
{
return $this->hasMany(EventDepartment::class);
}
}
class EventDepartment extends Model
{
public function event_location()
{
return $this->belongsTo(EventLocation::class, 'location_id');
}
}
的迁移EventDepartment
包含location_id
作为外键,如下所示:
Schema::create('event_departments', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->foreignId('location_id')->constrained('event_locations');
$table->softDeletes();
$table->timestamps();
});
EventDepartment
我现在面临的问题是,在基于外键创建新部门时,如何使表中的列唯一location_id
?
即,如果 EventDepartment 属于相同的 EventLocation,则它们不能具有具有相同名称的列,但我可以使用现有名称创建另一个 EventDepartment,只要它属于不同的 EventLocation
我已经尝试过,但没有工作:
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|min:3|unique:event_departments,location_id',
'location_id' => 'required',
]);
$department = EventDepartment::create([
'name' => $request->name,
'location_id' => $request->location_id,
]);
return new EventDepartmentResource($department);
}
解决方案
在创建迁移时,您应该通过相关字段设置唯一性。在您的示例中,它应该是name
和location_id
public function up()
{
Schema::create('event_departments', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->foreignId('location_id')->constrained('event_locations');
$table->softDeletes();
$table->timestamps();
$table->unique(['name', 'location_id'], 'unique_name_location');
});
}
public function down()
{
Schema::enableForeignKeyConstraints();
Schema::table('event_departments', function (Blueprint $table) {
$table->dropForeign(['location_id']);
$table->dropUnique('unique_name_location');
})
Schema::disableForeignKeyConstraints();
Schema::drop('event_departments');
}
这将确保数据库级别,表的既定规则,并且不会有多个具有相同 location_id 的同名。文档。
在 PHP 级别上,您必须编写自己的规则类来触发并检查 DB 可以接受的规则。
-制作一个规则类
php artisan make:rule UniqueNameLocationRule
- 规则类代码
public function __construct(string $name, int $locationId)
{
$this->name = $name;
$this->locationId = $locationId;
}
public function passes($attribute, $value)
{
return !EventDepartment::where([
'name' => $this->name,
'location_id' => $this->locationId,
])->exists();
}
-验证码
'name' => ['bail', 'required', 'min:3', new UniqueNameLocationRule((string)$request->name, (int)$request->location_id)],
'location_id' => ['required', 'exists:event_locations,id'],
文档。
这应该可以,请测试并判断是否有错误。
推荐阅读
- python - python的日期时间格式化程序适用于一个字符串,而不适用于另一个
- json - 如何通过powershell将值和键添加到现有的JSON文件中?
- python - 该函数未按预期提供输出
- javascript - 使用 Context 修复 React Native 应用程序中的“无法从不同组件的函数体内更新组件”警告
- django - Django + 角
- python - 如何在 Selenium Python 中搜索后返回第一个 Youtube 视频的链接?
- google-api - Google 用户:列出特定组的用户数据
- email - Plesk - 将邮件转发到 gmail 或直接在 gmail 中使用 POP3 获取?
- javascript - 盖茨比 activeClassName 不工作预览
- shell - 从交互式 go cli 中终止 shell 管道