【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【2024年2月~】25年卒 エンジニア新卒採用の募集を開始!

【2024年2月~】25年卒 エンジニア新卒採用の募集を開始!

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【WordPress 専用】クラウドサーバー『ウェブスピード』

【WordPress 専用】クラウドサーバー『ウェブスピード』

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

Laravelで中間テーブルを使いたい! syncメソッドの使い方

お疲れ様です!
システム開発部の山田です。

今回は、Laravelで中間テーブルを用いる際に使用するsyncメソッドについて解説していきます。

syncメソッドとは?

テーブルの関係性が多対多の場合、解決法として基本的に中間テーブルを用いると思います。
その際に、中間テーブルへのデータ登録や更新、削除といった動作をsyncメソッドを用いることで簡単に行うことができる優れものです。
具体的な実例とともに見ていきます。

準備(テーブル構成)

syncメソッドの使用にあたり以下状況を想定します。

  • ユーザーと趣味を紐づけ関係性にコメントを付与したい
  • 1ユーザーは趣味を複数持つことができる
  • 1 つの趣味は複数のユーザーから選ばれる

上記を達成するためのテーブル構成は以下を想定します。

  • ユーザーの名前を保持するusersテーブル
id name
1 taro
2 hanako
3 saburo
  • 趣味を名称を保持するhobbiesテーブル
id name
1 映画
2 youtube
3 勉強
  • ユーザーと趣味を関係を表し、コメントを付与できる中間テーブル(hobby_userテーブル
id user_id hobby_id comment
1 1 1 結構すき
2 1 2 そこそこすき
3 2 1 結構すき

以上内容でLaravelでマイグレーションファイルを用意し、users、hobbiesテーブルには記載しているデータを挿入した前提で以降の話を進めます。

準備(Laravelのモデルファイル)

Laravelのモデルファイルに多対多の関係性を表すために以下を記述します。

// hobbyモデル
public function users()
{
    return $this->belongsToMany(User::class);
}

// usersモデル
public function hobbies()
{
    return $this->belongsToMany(Hobby::class);
}

以上よりsyncメソッドの使用準備が整いましたので以降より使用していきます。

syncメソッド

それでは、まずはデータの登録を行いたいと思います。
taro(user_id:1)の趣味に映画(hobby_id:1)を追加したい場合は以下で表せます。

$user = User::find(1);
$user->hobbies()->sync(1);

コメントや複数の登録を一度に行いたい場合は、以下で表せます。
taro(user_id:1)の趣味にyoutube(hobby_id:2)、勉強(hobby_id:3)を追加しコメントも記載を想定します。

$user = User::find(1);
$user->hobbies()->sync([
    2 => ['comment' => '結構すき'],
    3 => ['comment' => 'そこそこすき'],
]);

ただし、ここで注意点があります。
以下は先ほどのtaro(user_id:1)の趣味に映画(hobby_id:1)を追加した状態のDBに
今回のコードを実行した場合のDBです。

taro(user_id:1)の趣味に映画(hobby_id:1)を追加したデータが消えております。
これはsyncメソッドが名前の通り、データの状態を指定した内容で同期を行うメソッドであるためです。
※sync: 同調・同期

この同期する性質を利用することでデータの削除、更新も簡単に行うことができます。
taro(id:1)の趣味を以下に変更する事を考えます。
youtube(hobby_id:2)、勉強(hobby_id:3)⇒映画(hobby_id:1)、youtube(hobby_id:2)

現状のDBは以下になります。

これを以下コードを実行した場合

$user = User::find(1);
$user->hobbies()->sync([1,2]);

結果は以下になります。

本来であれば勉強(hobby_id:3)の削除⇒映画(hobby_id:1)の追加を行うところを、syncメソッドを用いることで一発で行うことができました。
また、挙動として知っておきたい箇所はid=2の部分です。
コメントは今回指定していませんが、そのまま残っております。
これは、同期するのはあくまでも指定したuser_idとhobby_idの関係性であり、hobby_id=2は変更する必要が無いため、レコードを更新や削除がされることなく、そのまま残っているためです。

syncメソッドの応用

syncメソッドは、同期するメソッドであると説明しましたが、実は同期をせずに登録のみを行うことも可能です。
その方法は第二引数にfalseを宣言する事です。
先ほどのテーブルに続きに、taro(id:1)の趣味に勉強(hobby_id:3)を追加してみます。

$user = User::find(1);
$user->hobbies()->sync(3, false);

第二引数にfalseを指定することで、元々存在していた映画(hobby_id:1)、youtube(hobby_id:2)は消えることなく、勉強(hobby_id:3)の追加に成功しました。
ただし、falseをつけるのは忘れやすい行動で、もし指定を行わなかった場合は意図せずデータを消す恐れがあります。
そのため、falseを指定する代わりにsyncWithoutDetachingメソッドを指定しても同様の内容を表します。

$user = User::find(1);
$user->hobbies()->syncWithoutDetaching(3);

まとめ

今回はLaravelで中間テーブルの登録や変更、削除を行う際に便利なsyncメソッドを紹介しました。
同期の性質を理解する事さえできれば非常に扱いやすいメソッドだと思います。
また、最後に紹介したsyncWithoutDetachingメソッドはlaravelの内部的にはsyncメソッドにfalseを指定した物を実行するだけですが、
こういった物が用意されている事で、うっかりミスを防ぐことができるので非常に使い勝手のいいメソッドですね。

皆さんもsyncメソッドを使いこなし、日々コーディングを楽しんで行いましょう!
それでは!!

最後に

私が所属するシステム開発のサービスサイト「SEKARAKU Lab(セカラク ラボ)」を開設しました。
ビヨンドは、サーバーの設計・構築から運用までをワンストップでお任せいただけますので、サーバーサイド開発でお困りの方はお気軽にお問い合わせください。
SEKARAKU Lab:https://sekarakulab.beyondjapan.com/

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
5
読み込み中...
5 票, 平均: 1.00 / 15
11,049
X facebook はてなブックマーク pocket
【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【2024年2月~】25年卒 エンジニア新卒採用の募集を開始いたします!

【2024年2月~】25年卒 エンジニア新卒採用の募集を開始いたします!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

この記事をかいた人

About the author

山田雄貴

2021年株式会社ビヨンド入社
趣味はカラオケやボードゲーム
ボードゲームのが一つの棚で収まりきらなくなったため、新しい棚を購入したいが、家に棚を置く場所が無く悲しんでいる。
金型の設計や営業の経験もあり、多種多様な経験を積みサーバーサイドエンジニアの仕事に落ち着いている。
現在はPHPやPythonを用いたサーバーサイドの開発に従事している。
将来的にはフロントエンドの言語も習得したく、ReactベースのフロントエンドフレームワークであるNext.jsが気になっている。