php 包含null的hasMany关系

sqxo8psd  于 2023-04-04  发布在  PHP
关注(0)|答案(2)|浏览(78)

我的设置:

我有2个模型:UserSetting
用户可以有许多设置:

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是一个Collection,它不包含settings表中user_id为null的任何行。它只包含user_id等于用户id的行。

bnl4lu3b

bnl4lu3b1#

合并两个结果或原始表达式如何?
我实现了你所有的代码,我可以看到同样的困难...所以我发现这些解决方案不是很优雅,但功能。

备选1 -合并结果:

//user
$u = DB::table('users')->join('settings', 'users.id', '=', 'settings.user_id')->get();
//settings without user_id
$n = DB::table('settings')->where('settings.user_id', '=', null)->get();
//all together
$result = $u->merge($n);

我在php artisan tinker上的输出

>>> $result = $u->merge($n);
=> Illuminate\Support\Collection {#3019
     all: [
       {#3015
         +"id": "2",
         +"name": "name 123",
         +"email": "teste123@teste.com",
         +"email_verified_at": "2020-04-22 20:54:06",
         +"password": "1111111111111111111",
         +"remember_token": "1111111111111111111",
         +"created_at": "2020-04-22 21:13:50",
         +"updated_at": "2020-04-22 21:13:50",
         +"user_id": "123",
         +"description": "desc",
         +"setting_key": "conf",
         +"setting_value": "configuration-configuration",
       },
       {#3031
         +"id": "1",
         +"user_id": null,
         +"description": "desc",
         +"setting_key": "conf",
         +"setting_value": "configuration-configuration",
         +"created_at": "2020-04-22 21:13:50",
         +"updated_at": "2020-04-22 21:13:50",
       },
     ],
   }

备选2 -原始表达式:

$id = 123;

$r = DB::select(DB::raw("select * from settings where settings.user_id in ('{$id}') or settings.user_id is null"));
svmlkihl

svmlkihl2#

这是一个真实的的“Laravel方式”解决方案,仍然允许你像往常一样使用关系。

public function settings(): HasMany
{
    // Build a relationship, like usual
    $relation = $this->hasMany(Setting::class);

    // Add our custom constraint to the underlying query
    $query = $relation->getQuery();
    $query->orWhereNull($relation->getQualifiedForeignKeyName());

    // Still return the relationship, like usual
    return $relation;
}

相关问题