
データベースのテーブルの多くは他のテーブルと関係性を持ちます。例えば posts
テーブルで管理されているブログの投稿は comments
テーブルで管理されている複数のコメントと関係しています。
テーブル同士の関係性をEloquent Modelを使えば簡単に定義することができます。今回はモデルを使った関係性の中でも1対多のリレーションについて定義と実際の利用方法をまとめます。
1対多を定義する
「SNSなどへの投稿(Post)」とそれに対する「コメント(Comment)」を想定してみましょう。
1対多の関係の場合、複数紐づくテーブルにもう一方のテーブルの id
がわかるように post_id
のようなカラムを持ちます。
※ post_id
のように他のテーブルのどのデータか判別するためのカラムを「外部キー」と呼びます

これによって、例えば posts
テーブルの1番の投稿に紐づくコメントは、 comments
テーブルの1番、5番だということがわかります。
また comments
テーブルの2番のコメントに紐づいている投稿は、 posts
テーブルの2番ということがわかります。
使用するモデルの作成
Post
モデルと Comment
モデルを作成します。
$ php artisan make:model Post
$ php artisan make:model Comment
コマンドを実行したら app
ディレクトリ配下に Post.php
と Comment.php
が作成されていればOKです👍
PostモデルにCommentモデルとのリレーションを定義する
Post
モデルにはhasMany
メソッドを利用して、 Commnet
モデルとのリレーションを表す comments
メソッドを実装できます。(1つの Post
に対して複数の Comment
が関係しているので、メソッド名は複数形です)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function comments()
{
return $this->hasMany('App\Comment');
}
}
モデルは自動的に外部キーを判断してくれます。例えば上記の例だと、Comment
モデルは post_id
という外部キーを持っていると判断してくれます。
もしも Comment
モデルが持っている外部キーが post_id
では無い場合、例えば published_post_id
という名前だった場合、以下のように hasMany
メソッドの第二引数を修正します。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function comments()
{
return $this->hasMany('App\Comment', 'published_post_id');
}
}
リレーションを利用する
Model同士のリレーションの定義ができたら、コントローラーとbladeでどのように利用するのかをみていきましょう。
Postモデルに紐づいたCommentをコントローラーで扱う
今回はControllerの中で利用することを想定して、以下のような PostsController
と indexアクション
を作成しました。
※ Post
モデルを利用するためにファイル上部で use App\Post;
と書かれていることを確認してください。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
class PostsController extends Controller
{
public function index()
{
//
}
}
1対多のリレーションは1つのデータに対して、複数のデータが紐づいていることを表す関係なので、まずはPost
モデルを使ってデータを1つ見つけます。以下の例では id = 1
のデータを取得します。
public function index()
{
$post = Post::find(1);
}
※ モデルをつかったデータ取得方法はこちらも記事を参考にしてください。
Laravel モデルの作成とデータ取得
1対多の関係の場合、Post
モデルが1つ見つかると紐づく Comment
モデルが見つかります。先ほど Post
モデルで hasMany
メソッドを使って定義した関数を利用することができます。
public function index()
{
// id = 1のデータを取得
$post = Post::find(1);
// $postに紐づくCommentをCollectionとして取得
$comments = $post->comments;
// $commentsはCollectionなのでループができる
foreach ($comments as $comment) {
//
}
}
これでコントローラーでモデルのリレーションを使ったデータ取得ができます。
Postモデルに紐づいたCommentをbladeで扱う
例えば PostsController
の indexアクション
が以下のような実装だったとします。
public function index()
{
$post = Post::find(1);
return view('home', ['post' => $post]);
}
id = 1
の Post
モデルを取得して、 home.blade.php
というviewファイルを返しています。
bladeファイルで $post
に紐づいている Comment
モデルを利用するにはどうすればいいでしょうか。コントローラーと同じく、 先ほど Post
モデルで hasMany
メソッドを使って定義した関数を利用することができます。
以下の例では仮に Post
モデルは title属性
、Comment
モデルにも title属性
を持っているものとします。
{{-- $postのtitle属性を表示します --}}
<p>{{ $post->title }}</p>
{{-- $postに紐づくCommentモデルをCollectionとして取得し、かつtitle属性を表示します --}}
@foreach($post->comments as $comment)
<p>{{ $comment->title }}</p>
@endforeach
※ $post
に紐づくコメントはCollectionとして取得するのでループを利用することに注意
※ 個人的にはbladeで $post->commnets
のように書くのではなく、コントローラーで変数に定義してから、bladeに渡してあげた方が読みやすいと思います。
これでbladeでモデルのリレーションを使ったデータ取得、表示ができます。
逆のリレーションを定義する
今まで Post
モデルから紐づいている Commnet
モデルを取得する方法をみてきましたが、逆に Commnet
モデルから紐づいている1つの Post
モデルを取得する方法をみていきます。
hasMany
メソッドを利用したリレーションの逆を表現する時には belongsTo
メソッドを利用します。Commnet
モデルに以下のように post
メソッドを実装してください。(1つの Commnet
に対して1つの Post
が関係しているので、メソッド名は単数形です)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function post()
{
return $this->belongsTo('App\Post');
}
}
上記の例では、 Commnet
モデルが post_id
という外部キーを持っているとLaravel側が自動的に判断してくれます。
もしも Commnet
モデルが持っている外部キーが post_id
では無い場合、例えば published_post_id
という名前だった場合、以下のように belongsTo
メソッドの第二引数を修正します。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function post()
{
return $this->belongsTo('App\Post', 'published_post_id');
}
}
ここまで来るとあとは今までと同じです。コントローラーでもbladeでも Comment
モデルに紐づいた Post
モデルを利用することができます。
※ Comment
モデルを利用するためにファイル上部で use App\Comment;
と書かれていることを確認してください。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Comment;
class CommentsController extends Controller
{
public function index()
{
// id = 1のデータを取得
$comment = Comment::find(1);
// $commentに紐づくPostモデルを取得
$post = $comment->post;
return view('home', ['comment' => $comment]);
}
}
{{-- $commentのtitle属性を表示します --}}
<p>{{ $comment->title }}</p>
{{-- $commentに紐づくPostモデルを取得し、かつtitle属性を表示します --}}
<p>{{ $comment->post->title }}</p>
※ $comment
に紐づく投稿は1つのためループは必要ないことに注意
まとめ
データベースのテーブルの多くは他のテーブルと関係性を持ちます。テーブル同士の関係性をEloquent Modelを使えば簡単に定義することができます。
今回はモデルを使った関係性の中でも1対多のリレーションについて定義と実際の利用方法をみてきました。
1対多の関係の場合、複数紐づくテーブルにもう一方のテーブルの id
がわかるように post_id
のようなカラムを持ちます。(このカラムを外部キーと言います)
リレーション(関係性)を定義する時には各モデルに hasMany
メソッド、 belongsTo
メソッドを利用して実装します。
コントローラーとbladeで利用する時にはモデルに実装した関数を使ってデータ取得をします。