отношение hasMany, включая ноль - PullRequest
1 голос
/ 23 апреля 2020

Мои настройки:

У меня есть 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 может иметь значение NULL, поскольку таблица settings имеет настройки по умолчанию.

Моя проблема:

Я хочу сделать так, чтобы отношение settings() также возвращало строки, где user_id равно нулю (это настройки по умолчанию, связанные с не указанным c пользователем).

То, что я пробовал до сих пор:

Это не сработало:

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 значение NULL. Он содержит только строки, в которых user_id равно идентификатору пользователя.

1 Ответ

0 голосов
/ 23 апреля 2020

Как насчет слияния двух результатов или необработанного выражения?

Я реализую весь ваш код и вижу ту же сложность ... Поэтому я нашел эти решения не очень элегантными, но функциональными.

Альтернатива 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 Ремесленник

>>> $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"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...