【发布时间】:2020-04-22 23:13:24
【问题描述】:
我的设置:
我有 2 个模型:User 和 Setting。
一个用户可以有很多设置:
public function settings(): HasMany
{
return $this->hasMany(Setting::class);
}
$user = User::with('settings')->find($id);
这里是迁移:
Schema::create('settings', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->uuid('user_id')->nullable()->index();
$table->text('description');
$table->string('setting_key');
//$table->json('setting_value')->nullable();
$table->text('setting_value')->nullable();
$table->timestamps();
});
user_id 列可以为空,因为settings 表具有默认设置。
我的问题:
我想让settings() 关系也返回user_id 为空的行(这些是默认设置,没有链接到特定用户)。
到目前为止我尝试了什么:
这不起作用:
public function settings(): HasMany
{
return $this->hasMany(Setting::class)->orWhereNull('settings.user_id');
}
这也不起作用,即使我的调试栏中的 sql 请求看起来不错:
$user = User::query()
->with([
'settings' => function (HasMany $query) {
$query->orWhereNull('settings.user_id');
},
// irrelevant stuff
])
->findOrFail($userId);
运行:
select * from `settings` where `settings`.`user_id` in ('123') or `settings`.`user_id` is null
无论如何,$user->settings 是一个集合,它不包含我的settings 表中的任何行,其中user_id 为空。它只包含user_id 等于用户id 的行。
【问题讨论】:
-
编写总是需要检查是否存在 user_id 的代码会随着应用程序的增长而变得很累。为什么不给系统定义一个user_id 1?
-
编写总是需要检查 user_id 是否等于 1 的代码会随着应用程序的增长而变得很累。为什么不给系统定义一个user_id null?
-
当涉及到数据库时,使用默认值通常比使用不存在的值更容易。但这只是一个想法......
-
我不这么认为。 “null”更具语义性,占用更少的磁盘/内存空间,并且允许保留外键约束。最后不得不处理“null”或“1”是一样的,但是当你有getter方法时这是一种享受。感谢您的建议,但我认为这超出了我的问题范围。
-
为什么不先查询设置再获取与用户的反比关系,而不是先查询用户再查询设置。因为
hasMany不会以任何方式返回在您使用的父模型上没有任何关系标识符的字段,在这种情况下是User模型。