こんにちは、ディレクターのエリカです。
Laravelでは Polymorphic Relationship についても簡単に利用できます。ひとつの関係で対象となるモデルを、複数のモデルと結びつけることができます。
たとえば、画像のライブラリのようなものを用意したとして、そこに登録された画像をブログ記事で利用したり、ユーザープロフィールで利用したりすることができるようになります。
それでは、この場合を例にして、利用方法をみていきます。いわゆる 多対多 の Polymorphic Relationship になります。
Polymorphic Relationship のテーブル定義
まず、必要なところだけを抜き出すと、それぞれのテーブル定義は以下のような形になるかと思います。
posts
id - Integer
title - String
users
id - Integer
name - String
images
id - Integer
url - String
これに対し、 Polymorphic Relationship で、関連づけるためのテーブルは以下のようになります。
imageables
image_id - Integer
imageable_id - Integer
imageable_type - String
image_id には、imagesテーブルのidが格納されます。
imageable_id には、 posts もしくは users テーブルのidが格納されます。
imageable_type には、imageable_id が posts もしくは users どちらのテーブルの id かを示すモデル名が格納されます。
Polymorphic Relationship なモデル
それを実現するモデルはそれぞれ次のようになります。
class Post extends Model
{
public function images()
{
return $this->morphToMany('App\Image', 'imageable');
}
}
class User extends Model
{
public function images()
{
return $this->morphToMany('App\Image', 'imageable');
}
}
class Image extends Model
{
public function posts()
{
return $this->morphedByMany('App\Post', 'imageable');
}
public function users()
{
return $this->morphedByMany('App\User', 'imageable');
}
}
これだけで、 Polymorphic Relationship が実現できます。
Polymorphic Relationship なデータの登録
データを登録してみます。
// 関連付けたい任意のImageのIDの準備
$images = [1,2];
// 任意のPostデータを準備
$post = Post::find(1);
// 任意のUserデータを準備
$user = User::find(1);
// 関連付け
$post->images()->sync($images);
$user->images()->sync($images);
上記のようなコードを実行するだけ完了です。
このとき、 imageables テーブルには、以下のようなデータが保存されます。
imageables
| image_id | imageable_id | imageable_type |
| 1 | 1 | App\Post |
| 2 | 1 | App\Post |
| 1 | 1 | App\User |
| 2 | 1 | App\User |
ここで、 imageable_type については、デフォルトでモデル名が格納されます。アプリケーションの内部構造と分離したい場合は、別の値を指定することもできます。
Polymorphic Relationship における識別名の指定
サービスプロバイダで以下のように指定することで、Polymorphic Relationship な識別名の指定が可能です。
use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
'posts' => 'App\Post',
'users' => 'App\User',
]);
このようにすると、先ほどのデータ登録は下記のようになります。
imageables
| image_id | imageable_id | imageable_type |
| 1 | 1 | posts |
| 2 | 1 | posts |
| 1 | 1 | users |
| 2 | 1 | users |
Polymorphic Relationship なデータの呼び出し
登録された Polymorphic Relationship なデータ参照するのも簡単です。
下記のように、それぞれ関連づけられた Image のデータにアクセスできます。
$post = Post::find(1);
foreach($post->images() as $image) {
// $image->url;
}
$user = User::find(1);
foreach($user->images() as $image) {
// $image->url;
}
まとめ
今回は、多対多な Polymorphic Relationship で、画像を例にしましたが、タグや、レビュー機能など、複数のモデルが対象になるような関連付けの際にとても有用かと思います。
Laravelなら Polymorphic Relationship も洗練されていますね。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。