1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravelのリレーションで、複数idのアタッチの際にリレーション先テーブルの追加カラムの値をidごとに指定する方法

Posted at

例えば、usersとticketsがあって、user_ticketsとういうテーブルがあったとしましょう。
以下のように、固有のチケットに対して複数のIDを付与したい場合

$users = User::factory(10)->create();
Ticket::factory()->create()->attach($users->pluck('id'));

こういった形になると思います。
attachの第2引数はattributesを指定できるので、

$users = User::factory(10)->create();
Ticket::factory()->create()->attach($users->pluck('id'), ['foo' => 'bar']);

といったように、user_ticketsの別カラム(foo)に対して一律でbarを設定することができます。

ただ、10件のユーザーがあったとして、それぞれで番号を切り替えたいといった要求の場合、この第2引数では解決できません。

こういった際、どうしたら良いかというと第1引数をkey=>valueな形式にして差し込むことで値を入れることが可能です。

$users = [
    1 => ['foo' => 'bar'],
    2 => ['foo' => 'baz'],
    3 => ['foo' => 'aaa'],
];
Ticket::factory()->create()->attach($users);

ModelFactoryのように、テストの用途でこういうことをしたい場合、以下のような感じにできます。
もちろん、UserTicketFactoryのようなものを用意する方法でも良さそうです。

例としては、番号をインクリメントさせてくことで、番号が一意であるようにするパターンです。

$sequence = 1;
$users = User::factory(10)->create()->pluck('id')->flip()->map(function() use (&$sequence)) {
    return ['index' => $sequence++];
}
Ticket::factory()->create()->attach($users);

チェーンが長くなってしまってますが、pluckでidのリストを抽出し、flipを利用してidをkeyに変換。mapで対象に値をセットしています。
(実際このパターンだと、mapメソッドの引数にvalue(元々keyだったものをひっくり返した数値)があるはずなので、それを利用するだけでも良さそうです)

おわり。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?