YuHo のブログ

Laravel, PHP, JavaScript

Laravel 5.6 でブログサイトを制作する2 #5 Comment モデルの追加

Comment モデルを追加する

Comment モデルを作成して、コメント用のデータベースの作成と利用に備えます。

モデルとマイグレーションファイルの作成

まずはモデルクラスファイルを作成します。

php artisan make:model Comment

つぎにコメント用のマイグレーションファイルを作成します。コメント用のテーブルを作成するためのクラスです。

php artisan make:migration create_comments_table --create=comments

マイグレーションファイルの編集

コメント用のマイグレーションファイルを編集します。コメントとその投稿者であるユーザーを紐付けるための user_id とコメントとその投稿先であるポストを紐付けるための post_id とコメントの内容を保存する content カラムを書き加えます。

<?php

public function up()
{
    Schema::create('comments', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id');
        $table->integer('post_id');
        $table->string('content');
        $table->timestamps();
    });
}

マイグレーションファイルの実行

マイグレートを実行してコメントテーブルを作成します。

php artisan migrate

Route を作成する

ルートを作成します。各コメントを表示するための専用のページは今回は作らないので、リソースルートから index, store, update, destroy だけを利用します。

[blog/routes/web.php]

<?php

Route::resource('comments', 'CommentController')->only([
    'index', 'store', 'update', 'destroy'
]);

Authorization を準備する

認証済みユーザーが各コメントに対する操作を許可されていることを確かめる仕組みを作成します。

Gate を作成する

これはなくてもいいです。

[blog/app/Providers/AuthServiceProvider.php]

<?php

public function boot()
{
    $this->registerPolicies();
        
    Gate::resource('comments', 'CommentPolicy');
}

CommentPolicy を作成する

コメント・ポリシー・クラスを作成します。

php artisan make:policy CommentPolicy --model=Comment

コメント・ポリシー・クラスとコメントクラスを紐づけます。

CommentPolicy を Comment モデルに紐付ける

[blog/app/Providers/AuthServiceProvider.php]

<?php

protected $policies = [
    'App\Model' => 'App\Policies\ModelPolicy',
    'App\User' => 'App\Policies\UserPolicy',
    'App\Post' => 'App\Policies\PostPolicy',
    'App\Comment' => 'App\Policies\CommentPolicy',
];

CommentPolicy を編集する

コメント・ポリシー・クラスの各メソッドを編集します。

[blog/app/Policies/CommentPolicy.php]

<?php

class CommentPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view the comment.
     *
     * @param  \App\User  $user
     * @param  \App\Comment  $comment
     * @return mixed
     */
    public function view(User $user, Comment $comment)
    {
        //
    }

    /**
     * Determine whether the user can create comments.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        return $user->id;
    }

    /**
     * Determine whether the user can update the comment.
     *
     * @param  \App\User  $user
     * @param  \App\Comment  $comment
     * @return mixed
     */
    public function update(User $user, Comment $comment)
    {
        return $user->id === $comment->user_id;
    }

    /**
     * Determine whether the user can delete the comment.
     *
     * @param  \App\User  $user
     * @param  \App\Comment  $comment
     * @return mixed
     */
    public function delete(User $user, Comment $comment)
    {
        return $user->id === $comment->user_id;
    }
}

CommnetController の作成

コメント・コントローラー・クラスを作成します。

作成

artisan コマンドで CommentController を作成します。

php artisan make:controller CommentController --resource --model=Comment

編集

[app/Http/Controllers/CommentController.php]

<?php

class CommentController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $comments = Comment::paginate(10);

        return view('comments.index', ['comments' => $comments]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $comment = new App\Comment;

        $comment->content = $request->input('content');
        
        $request->user()->comments()->save($comment);
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Comment  $comment
     * @return \Illuminate\Http\Response
     */
    public function show(Comment $comment)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Comment  $comment
     * @return \Illuminate\Http\Response
     */
    public function edit(Comment $comment)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Comment  $comment
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Comment $comment)
    {
        $comment->content = $request->input('content');

        $request->user()->comments()->save($comment);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Comment  $comment
     * @return \Illuminate\Http\Response
     */
    public function destroy(Comment $comment)
    {
        $comment->delete();
    }
}

Blade を作成する

コメントのデータを表示するためのブレードを作成します。

[blog/resources/views/posts/index.blade.php]

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Comment Index</div>

                <div class="card-body">
                    @foreach($comments as $comment)
                    <div>
                        <a href="{{ route('posts.show', ['post' => $comment->post_id]) }}">{{ $comment->post->title }}</a>
                        <a href="{{ route('users.show', ['user' => $comment->user_id]) }}">{{ $comment->user->name }}</a>
                        <p>{{ $comment->content }}</p>
                    </div>
                    @endforeach
                </div>

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

Seeder を作成する

作成

php artisan make:seeder CommentsTableSeeder

DatabaseSeeder.php の編集

php

[blog/database/seeds/DatabaseSeeder.php]

call([
UsersTableSeeder::class,
PostsTableSeeder::class,
CommentsTableSeeder::class,
]);
}
|

CommentFactory を作成する

[blog/database/factories/CommentFactory.php]

<?php

use Faker\Generator as Faker;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

$factory->define(App\Post::class, function (Faker $faker) {
    return [
        'content' => $faker->name,
    ];
});

CommentsTableSeeder.php の編集

[blog/database/seeds/CommentsTableSeeder.php]

<?php

public function run()
{
    factory(App\Post::class, 30)->create();
}

Seeder を実行する

composer dump-autoload
php artisan migrate:refresh --seed

補足

app.blade.php を編集する

app.blade.php に comments.index 用のリンクを追加します。

[blog/resources/views/layouts/app.blade.php]

<!-- Left Side Of Navbar -->
<ul class="navbar-nav mr-auto">
    <li><a class="nav-link" href="{{ route('users.index') }}">Users</a></li>
    <li><a class="nav-link" href="{{ route('posts.index') }}">Posts</a></li>
    <li><a class="nav-link" href="{{ route('comments.index') }}">Comments</a></li>
</ul>