前回はフロントのトップページを実装しましたが、今回はカテゴリー機能を追加していきます。ユーザーが設定したカテゴリー毎に、ブログ記事を分類する、ブログによくある機能のことです。それでは管理画面から実装していきます。
テーブルの追加・カラムの追加
それではまずは、カテゴリーを保存する 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
というファイルができるので、それを下記のように編集します。
<?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
というファイルができるので、それを開いて下記のように編集します。
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
を開いて、下記のように編集します。
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
として、このファイルを下記のように編集します。
<?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 メソッドを追加します。
<?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
ファイルを新規に作成して、カテゴリ一覧画面を作っていきます。
@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文を発行して、データを作成してください)。
うまくできたら、下記のような画面になっていると思います。
次回は、カテゴリーの追加・編集、削除APIを実装します。