
こんにちは、最近パワプロ2016を購入しホモころがし理論に勤しむ制作の奥田です。
パワプロ2016神ゲー確定ですね。
今期アニメは「甲鉄城のカバネリ」と「Re:ゼロ」が圧倒的覇権アニメですね。
さて、WordPressなどでもうおなじみですが、フレームワークで投稿とタグの関係を作るとき「多対多」のリレーションが必須になってきます。
LaravelにはBelongsToManyというリレーションが用意されています。
BelongsToManyとは以下のように中間テーブルを使用したJOINの方法です。
| posts | id |
| title | |
| body |
| tags | id |
| name |
| post_tag | post_id |
| tag_id |
今回はLarabelを使ったBelongsToManyの実装方法と検索方法までをやってみたいと思います。
Table of contents
データベースを作成
まず、それぞれの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を使用するとデータベースの設計など少し進んだ分野も手軽に学習できるメリットが有ると思います。
ぜひお役に立ててください。