14
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravel5 チュートリアル ブログもどきを作る(8) カテゴリー機能を追加する

Last updated at Posted at 2018-08-19

前回はフロントのトップページを実装しましたが、今回はカテゴリー機能を追加していきます。ユーザーが設定したカテゴリー毎に、ブログ記事を分類する、ブログによくある機能のことです。それでは管理画面から実装していきます。

テーブルの追加・カラムの追加

それではまずは、カテゴリーを保存する categories テーブルを作成します。

テーブルスキーマ

下記のスキーマで categories テーブルを作成します。

物理名 論理名 NOT NULL デフォルト 備考
category_id カテゴリーID int(10) unsigned YES auto_increment, PK
name カテゴリー名 varchar(255) YES
display_order 表示順 smallint(5) unsigned YES
deleted_at 削除日時 timestamp NO NULL 論理削除用カラム
created_at 作成日時 timestamp NO NULL
updated_at 更新日時 timestamp NO NULL

カラム追加

articles テーブルに category_id カラムを追加します。category_id カラム追加後のスキーマは下記のようになります。

物理名 論理名 NOT NULL デフォルト 備考
article_id 記事ID int(10) unsigned YES auto_increment, PK
caetgory_id カテゴリーID int(10) unsigned YES 新しく追加
post_date 投稿日 date YES
title タイトル varchar(255) YES
body 本文 text YES
deleted_at 削除日時 timestamp NO NULL 論理削除用カラム
created_at 作成日時 timestamp NO NULL
updated_at 更新日時 timestamp NO NULL

マイグレーションファイル作成

続いて categories テーブルを作るためのマイグレーションファイルを作成すると同時に、Category モデルクラスも同時に作成します。Laravel ホームディレクトリに移動して、下記コマンドを実行します。

php artisan make:model Category --migration

そうすると、database/migrations/{$timestamp}_create_categories_table.php というファイルができるので、それを下記のように編集します。

database/migrations/{$timestamp}_create_categories_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->increments('category_id');
            $table->string('name');
            $table->unsignedSmallInteger('display_order');
            $table->softDeletes();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('categories');
    }
}

続いて articles テーブルに category_id カラムを追加するためのマイグレーションファイルを作成します。articles テーブルを作ったときに作成したマイグレーションファイルを編集するのではなく、新しくマイグレーションファイルを作ります(私は、そうとは知らずにハマったことがあります・・・)。
Laravel ホームディレクトリで下記コマンドを打って、カラム追加用のマイグレーションファイルを作成します。

php artisan make:migration add_category_id_column_to_articles_table

そうすると、database/migrations/{$timestamp}_add_category_id_column_to_articles_table.php というファイルができるので、それを開いて下記のように編集します。

database/migrations/{$timestamp}_add_category_id_column_to_articles_table.php
class AddCategoryIdColumnToArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // 既に存在するテーブルの更新には table メソッドを使う
        Schema::table('articles', function(Blueprint $table) {
            // after メソッドでカラムを追加する位置を指定できる(MySQLのみ)
            $table->unsignedInteger('category_id')->after('article_id');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('articles', function(Blueprint $table) {
            // カラムを削除するときは dropColumn メソッドを使う
            $table->dropColumn('category_id');
        });
    }
}

編集ができたら、下記コマンドを叩いて、マイグレーションを実行します。

php artisan migrate

実行できたら、意図した通りに categories テーブルができているか、articles テーブルに category_id が追加されているか確認してください。

ルーティングの追加

管理画面のカテゴリ一覧画面、追加・編集、削除処理のルーティングを追加します。今回は、追加・編集と削除処理についてはAPIを作成し、それを利用してDBにカテゴリーデータを保存・削除します。routes/web.php を開いて、下記のように編集します。

routes/web.php
Route::prefix('admin')->group(function() {
    Route::get('form/{article_id?}', 'AdminBlogController@form')->name('admin_form');
    Route::post('post', 'AdminBlogController@post')->name('admin_post');
    Route::post('delete', 'AdminBlogController@delete')->name('admin_delete');
    Route::get('list', 'AdminBlogController@list')->name('admin_list');

    Route::get('category', 'AdminBlogController@category')->name('admin_category');
    Route::post('category/edit', 'AdminBlogController@editCategory')->name('admin_category_edit');
    Route::post('category/delete', 'AdminBlogController@deleteCategory')->name('admin_category_delete');
});

下から3つが今回追加したルーティングになります。
(今回はカテゴリー一覧画面を作成します。カテゴリーの追加・編集と削除処理については次回になります)

モデルの作成

続いて、先ほど作った categories テーブルのモデルクラス Cateogry を作成します。マイグレーションファイルを作るとき、同時に app/Category.php が作られていると思いますので、それを Models ディレクトリに移動し app/Models/Category.php として、このファイルを下記のように編集します。

app/Models/Category.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Category extends Model
{
    use SoftDeletes;

    protected $primaryKey = 'category_id';
    protected $fillable = ['name', 'display_order'];
    protected $dates = ['deleted_at', 'created_at', 'updated_at'];

    /**
     * カテゴリリストを取得する
     *
     * @param int    $num_per_page 1ページ当たりの表示件数
     * @param string $order        並び順の基準となるカラム
     * @param string $direction    並び順の向き asc or desc
     * @return mixed
     */
    public function getCategoryList(int $num_per_page = 0, string $order = 'display_order', string $direction = 'asc')
    {
        $query = $this->orderBy($order, $direction);
        if ($num_per_page) {
            return $query->paginate($num_per_page);
        }
        return $query->get();
    }
}

特に目新しいことはしていません。ソフトデリート(論理削除)の設定、各プロパティの設定の他に、カテゴリ一覧を取得するメソッド getCategoryList() を実装しています。

コントローラーの編集

コントローラーを編集して、カテゴリ一覧画面を表示するためのメソッドを追加します。app/Http/Controllers/AdminBlogController.php を開いて、下記の category メソッドを追加します。

app/Http/Controllers/AdminBlogController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\AdminBlogRequest;
use App\Models\Article;
use App\Models\Category;

class AdminBlogController extends Controller
{
    /** @var Article */
    protected $article;
    /** @var Category */
    protected $category;

    // 1ページ当たりの表示件数
    const NUM_PER_PAGE = 10;

    function __construct(Article $article, Category $category)
    {
        $this->article = $article;
        $this->category = $category;
    }

    ...中略...

    /**
     * カテゴリ一覧画面
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function category()
    {
        $list = $this->category->getCategoryList(self::NUM_PER_PAGE);
        return view('admin_blog.category', compact('list'));
    }

まず、コンストラクターインジェクションで Category モデルクラスのインスタンスを生成します。そして、category メソッドは、先ほど作った getCategoryList() を使ってカテゴリリストを取得し、それを View に渡すだけのシンプルな作りですね。

Viewテンプレートの作成

続いて resources/views/admin_blog/ 配下に category.blade.php ファイルを新規に作成して、カテゴリ一覧画面を作っていきます。

resources/views/admin_blog/category.blade.php
@extends('admin_blog.app')
@section('title', 'カテゴリ一覧')

@section('body')
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h2>カテゴリ一覧</h2>
                <br>

                @if (count($list) > 0)
                    <br>
                    {{ $list->links() }}
                    <table class="table table-striped">
                        <tr>
                            <th width="120px">カテゴリ番号</th>
                            <th>カテゴリ名</th>
                            <th width="60px">表示順</th>
                        </tr>

                        @foreach ($list as $category)
                            <tr data-category_id="{{ $category->category_id }}">
                                <td>
                                    <span class="category_id">{{ $category->category_id }}</span>
                                </td>
                                <td>
                                    <span class="name">{{ $category->name }}</span>
                                </td>
                                <td>
                                    <span class="display_order">{{ $category->display_order }}</span>
                                </td>
                            </tr>
                        @endforeach
                    </table>
                @else
                    <br>
                    <p>カテゴリがありません。</p>
                @endif

            </div>
        </div>
    </div>
@endsection

ここまでできたら、実際に画面を表示させて、カテゴリー一覧がちゃんと表示されることを確認してください(カテゴリーデータが無いと思うので、手動でinsert文を発行して、データを作成してください)。
うまくできたら、下記のような画面になっていると思います。

category_list.png

次回は、カテゴリーの追加・編集、削除APIを実装します。

参考資料

Laravel 日本語ドキュメント

プログラムソース(github)

14
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?