【Laravel6】投稿機能の実装【1対多】

本日は、1人のユーザーが複数の投稿をする(1対多)機能を実装します。

投稿機能のER図


ログイン機能を実装した際にusersテーブルは作成されているので、今回はpostsテーブルを作成します。

postsテーブルを作成

新しいテーブルを作成するためにマイグレーションを作成

1、artisanコマンドでマイグレーション作成

[mac] $ php artisan make:migration create_posts_table --create=posts

2、database/migrationsのposts_table.phpに追記し保存

public function up()
  {
    Schema::create('posts', function (Blueprint $table) {
      $table->bigIncrements('id');
      $table->string('post_title');
      $table->string('post_content');
      $table->integer('user_id');
      $table->timestamps();
    });
  }

3、マイグレーションの実行(テーブルの作成)

[mac] $ php artisan migrate

マイグレーションが成功すると、画像のようにpostsテーブルが追加されます。

モデルを作成

1、artisanコマンドでモデル作成

[mac] $ php artisan make:model Post

2、モデルにリレーションの設定を追加する

App/User.phpに追記します。

// postsテーブルとのリレーション(主テーブル側)
  public function posts() { //1対多の「多」側なので複数形
    return $this->hasMany('App\Post');
  }

App/Post.phpに追記します。

// usersテーブルとのリレーション(従テーブル側)
  public function user() { //1対多の「1」側なので単数系
    return $this->belongsTo('App\User');
  }

投稿画面表示の実装

Postsコントローラーを作成

[mac] $ php artisan make:controller PostsController --resource

Postsコントローラー内にモデル呼び出し&indexメソッドに表示処理を追加

use App\Post;
use App\User;
use Auth;
use Validator;

public function index()
  {
    // 全ての投稿を取得
    $posts = Post::get();

    return view('posts',[
      'posts'=> $posts
    ]);
  }

Postsコントローラー内のstoreメソッドに登録処理を追加

public function store(Request $request)
{
   //バリデーション
  $validator = Validator::make($request->all(), [
    'post_title' => 'required|max:255',
    'post_content' => 'required|max:255',
  ]);

  //バリデーション:エラー
  if ($validator->fails()) {
    return redirect('/')
        ->withInput()
        ->withErrors($validator);
  }

  //以下に登録処理を記述(Eloquentモデル)
    $posts = new Post;
    $posts->post_title = $request->post_title;
    $posts->post_content = $request->post_content;
    $posts->user_id = Auth::id();//ここでログインしているユーザidを登録しています
    $posts->save();

    return redirect('/');
}

web.phpに投稿ページと投稿処理のルーティングを追加

// 投稿画面の表示
Route::get('/', 'PostsController@index');
// 投稿処理
Route::post('posts', 'PostsController@store');

投稿と一覧表示を実装

/resources/views/posts.blade.phpを作成(投稿フォーム)

@extends('layouts.app')
@section('content')
<div class="card-body">
  <div class="card-title">
    投稿フォーム
  </div>
  <!-- バリデーションエラーの表示に使用-->
  @include('common.errors')
    <!-- 投稿フォーム -->
    @if( Auth::check() )
      <form action="{{ url('posts') }}" method="POST" class="form-horizontal">
      {{ csrf_field() }}
      <!-- 投稿のタイトル -->
      <div class="form-group">
        投稿のタイトル
        <div class="col-sm-6">
          <input type="text" name="post_title" class="form-control">
        </div>
      </div>
      <!-- 投稿の本文 -->
      <div class="form-group">
      投稿の本文
        <div class="col-sm-6">
          <input type="text" name="post_content" class="form-control">
        </div>
      </div>
      <!-- 登録ボタン -->
      <div class="form-group">
        <div class="col-sm-offset-3 col-sm-6">
          <button type="submit" class="btn btn-primary">
            Save
          </button>
        </div>
      </div>
    </form>
  @endif
</div>
  <!-- 全ての投稿リスト -->
  @if (count($posts) > 0)
    <div class="card-body">
      <div class="card-body">
        <table class="table table-striped task-table">
        <!-- テーブルヘッダ -->
        <thead>
          <th>投稿一覧</th>
          <th> </th>
        </thead>
        <!-- テーブル本体 -->
        <tbody>
          @foreach ($posts as $post)
            <tr>
              <!-- 投稿タイトル -->
              <td class="table-text">
                <div>{{ $post->post_title }}</div>
              </td>
              <!-- 投稿詳細 -->
              <td class="table-text">
                <div>{{ $post->post_content }}</div>
              </td>
              <!-- 投稿者名の表示 -->
              <td class="table-text">
                <div>{{ $post->user->name }}</div>
              </td>
          </tr>
        @endforeach
     </tbody>
    </table>
  </div>
</div>
@endif
@endsection

エラー表示の作成

/resources/views/common/errors.blade.phpを作成

@if (count($errors) > 0)
  <!-- Form Error List -->
  <div class="alert alert-danger">
   <div><strong>入力した文字を修正してください。</strong></div>
   <div>
    <ul>
     @foreach ($errors->all() as $error)
      <li>{{ $error }}</li>
     @endforeach
    </ul>
  </div>
 </div>
@endif

投稿機能の実装完了

ログインしてないときの表示(投稿フォーム非表示)

ログイン時の表示(投稿フォーム表示)

  • B!