Blog スタッフブログ

Laravel5.2で多対多(BelongsToMany)のリレーション

Category | Blog
Tag | /
/ 1,763views

laravel-belongsToMany

こんにちは、最近パワプロ2016を購入しホモころがし理論に勤しむ制作の奥田です。
パワプロ2016神ゲー確定ですね。

今期アニメは「甲鉄城のカバネリ」と「Re:ゼロ」が圧倒的覇権アニメですね。

さて、WordPressなどでもうおなじみですが、フレームワークで投稿とタグの関係を作るとき「多対多」のリレーションが必須になってきます。
LaravelにはBelongsToManyというリレーションが用意されています。
BelongsToManyとは以下のように中間テーブルを使用したJOINの方法です。

posts id
title
body
tags id
name
post_tag post_id
tag_id

今回はLarabelを使ったBelongsToManyの実装方法と検索方法までをやってみたいと思います。

データベースを作成

まず、それぞれのDBを作成します。
すでにpostsテーブルやtagsが存在する場合でもそれぞれに影響を与えることなく実装できるのもこのリレーションの素晴らしいところですね。

php artisan make:migration create_posts_table #すでにある場合は必要ありません。
php artisan make:migration create_tags_table #すでにある場合は必要ありません。
php artisan make:migration create_post_tag_table

各migrationファイルは以下のようにします。

# create_posts_table.php
Schema::create('posts', function (Blueprint $table) {
    $table->increments('id');
    $table->string('title');
    $table->text('body');
});

# create_tags_table.php
Schema::create('tags', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
});

# create_post_tag_table.php
Schema::create('post_tag', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('post_id');
    $table->integer('tag_id');
});

マイグレーションします。

php artisan migrate

テーブルの作成ができたらモデルを作成し、Postモデルにリレーションを設定します。

php artisan make:model Tags 
php artisan make:model PostTag

#Post.php
public function tags()
{
	return $this->belongsToMany('App\Tag');
}

投稿画面にタグの選択を配置する

タグの追加画面は省略します。それぞれの管理画面に合った投稿画面を作成してください。
投稿画面にタグ選択用のチェックボックスを実装します。

#PostsController.php	
// 記事から選択中のタグのリストを取得
$tags = $post->tags->lists("id")->toArray();
// タグのリストを取得 
$tagList = Tag::get()->lists("name","id");

// Viewにセットします。
return view('admin.posts.edit',[
           'post' => $post,
           'tagList' => $tagList,
           'tags' => $tags,
]);

ビュー側で表示します。

@foreach ($tagList as $k => $tag) 
<label class="checkbox">
	<input type="checkbox" name="tags[]" value="{{$k}}" @if(in_array($k,$tags)) checked @endif>
	{{ $tag }}
</label>
@endforeach

保存時に同時にタグも保存する

データベースに保存する際に同時に保存します。

// 選択したタグを保存
$post->tags()->sync(\Request::input('tags', []));
$post->save();

タグから記事を検索する

検索する際はpost_tagテーブルから一致したものを検索し、それをwhereInに入れることで実装します。
まず、投稿画面と同じようにして検索フォームにcheckboxを作成します。

@foreach ($tagList as $k => $tag) 
<label class="checkbox">
	<input type="checkbox" name="tags[]" value="{{$k}}" >
	{{ $tag }}
</label>
@endforeach

PostsController.phpに以下のメソッドを追記します。

# PostsController.php
public function getPostIdByTags($tags){
    $query = PostTag::query();
    foreach($tags as $id){
        $query->orWhere('tag_id', $id);
    }
    return $query->get()->lists("post_id");
}

絞り込みをする箇所で以下のようにして一致したidからpostsテーブルのidを絞り込みます。

$query  = Post::query();
$tags   = \Request::get('tags');
if ($tags) {
    $query->whereIn('id', $this->getPostIdByTags($tags));
}

これで検索の際に一致したタグを持つ記事が絞り込めます。

最後に

「多対多」のリレーションについて簡単にご説明しました。
LaravelでEloquentを使用するとデータベースの設計など少し進んだ分野も手軽に学習できるメリットが有ると思います。
ぜひお役に立ててください。

Category | Blog
Tag | /
Author | Mineo Okuda / 1,763views

Company information

〒651-0087
神戸市中央区御幸通 8-1-6 神戸国際会館 22F

Contact us

WEBに関するお問い合わせは
078-570-5755 (10:00 - 18:00)