見出し画像

Laravel 5.7 でコンテンツ投稿機能を実装する

Laravel 5.7にてコンテンツ投稿機能を実装する方法を記載します。

今回やること
・投稿機能の設計を行う
・投稿された情報を格納する「posts」テーブル作成
・Postモデルを作成する
・投稿フォームページのルーティングを設定する
・Post コントローラーを作成する
・投稿フォーム用viewを作成
・詳細ページ表示用viewを作成
・投稿フォームより投稿したデータが「posts」テーブルに格納される
前提
・Laravelが動く環境がすでにあること
・すでにDBが作成されていること
・Laravel のバージョンは5.7

完成動画はこちらです。

それでは始めます。

--- 🖥 ---

投稿機能の設計を行う

今回作成する投稿機能の設計を行います。

URL設計

URL設計は下記のようにします。

投稿フォームページ:/post
投稿内容表示ページ:/post/[post_id]

テーブル定義

テーブル定義は下記のようにします。
※テーブル定義は「フィールド名 / 物理名 /データ型」の順で記載します。

id / コンテンツID / integer
title / タイトル / VARCHAR
content / コンテンツ / text
user_id / ユーザID /integer
created_at / 作成日 / TIMESTAMP
updated_at / 更新日 / TIMESTAMP
※user_idは投稿者のユーザIDを自動で取得するようにします。

以上で設計を終わります。


投稿された情報を格納する「posts」テーブル作成

それでは次に「posts」テーブルを作成します。
テーブル作成にあたり、マイグレーションファイルを作成します。

※マイグレーションについてはこちらの記事が詳しいです。

下記コマンドを実行し、postsテーブル作成のためのマイグレーションファイルを作成します。

php artisan make:migration create_posts_table --create=posts

すると、「database/migrations」ディレクトリ内に「2019_02_04_030213_create_posts_table.php」のようなファイル名のファイルが作成されます。

※2019_02_04_030213は作成した日時ですので、作成日時により異なります。

こちらのファイルを、最初に行ったテーブル定義を元に修正します。念のためテーブル定義を再度記載しておきます。

id / コンテンツID / integer
title / タイトル / VARCHAR
content / コンテンツ / text
user_id / ユーザID /integer
created_at / 作成日 / TIMESTAMP
updated_at / 更新日 / TIMESTAMP
※user_idは投稿者のユーザIDを自動で取得するようにします。

以下のように記載します。

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
   /**
    * Run the migrations.
    *
    * @return void
    */
   public function up()
   {
       Schema::create('posts', function (Blueprint $table) {
           $table->increments('id');
           $table->string('title');
           $table->text('content');
           $table->integer('user_id')->unsigned();
           $table->timestamps();
           $table->foreign('user_id')->references('id')->on('users');
       });
   }
   /**
    * Reverse the migrations.
    *
    * @return void
    */
   public function down()
   {
       Schema::dropIfExists('posts');
   }
}
■↑のポイント
・up メソッド内に作成するフィールド情報を記載します。
・$table->timestamps()によって、作成日と更新日が作成されます。 
・user->idは「users」テーブルより自動取得なので、『$table->foreign('user_id')->references('id')->on('users');』のような書き方となります。

以上でファイル作成完了です。ファイルができたので下記コマンドでマイグレーションを実行します。

php artisan migrate

コマンド実行後にデータベースを確認すると、postsテーブルが作成されています。

↑PHPMyAdminで確認した図

以上でテーブルの作成は終わりです。


Postモデルを作成する

次にモデルを作成します。モデルはデータベースとの連携のために必要になります。

※モデルについてはこちらの記事をご覧ください。

モデルにはルールがあります。上で紹介した記事から引用します。

LaravelのModelには命名規則があります。
例えば、テーブル名がusersの場合、Model名はUserになります。
テーブル名を単数形にしたものがModel名となり、自動的にテーブルを操作することができるようになります。

ということなので、今回は「posts」に対応するモデルなので、「Post」というモデルを作成します。以下実行します。

php artisan make:model Post

すると、「/app」ディレクトリに「Post.php」というファイルが作成されます。今回は下記のように修正します。

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
   protected $fillable = ['title', 'content', 'user_id'];
}
■↑のポイント
・「fillable」の設定をすることによって、予期せぬ代入が起こることを防ぐことができます。詳しくはこちらをご覧ください。

以上でモデルの作成は完成です。


投稿フォームページのルーティングを設定する

次にweb.phpにて投稿フォームのルーティングの設定をします。URL設計のおさらいをすると

投稿フォームページ:/post
投稿内容表示ページ:/post/[post_id]

となります。「/routes/web.php」に下記追加します。

//投稿フォームページ
Route::get('/post', 'PostController@showCreateForm')->name('posts.create');
Route::post('/post', 'PostController@create');

//投稿確認ページ
Route::get('/post/{post}', 'PostController@detail')->name('posts.detail');
■↑のポイント
・投稿フォームを表示するために「PostController@showCreateForm」を指定しています。
・投稿フォームのロジック(DBへの代入)のために、「PostController@create」を指定しています。
・投稿確認ページのために、「PostController@detail」を指定しています。

こうすることによって、
「/post」で投稿フォームが表示され
「/post/[post_id]」で投稿された内容が表示される
ようになります。

以上でルーティングの設定は完了です。


Post コントローラーを作成する

次にコントローラーを作成します。先ほどのルーティングの際にコントローラーを指定したので、それに基づいてコントローラーを作成します。
コントローラーの作成は、下記コマンド実行で対応できます。

php artisan make:controller PostController

こちら実行すると、「/app/Http/Controllers」ディレクトリに、「PostController.php」が作成されています。
PostController.php修正します。順に説明していきます。

1. PostController@showCreateForm の作成。

まずは投稿フォームの設定です。下記追記します。

    public function showCreateForm()
   {
       return view('posts/create');
   }
■↑のポイント
web.phpで記載した、「showCreateForm」の設定です。
こうすることで、「/post」にアクセスした時に、「/resources/views/posts/create.blade.php」ファイルを見に行くと指定しています。

2. PostController@createの作成

次に投稿時のロジック部分です。コントローラーに下記追加します。

public function create(Request $request)
   {
       // Postモデルのインスタンスを作成する
       $post = new Post();
       // タイトル
       $post->title = $request->title;
       //コンテンツ
       $post->content = $request->content;
       //登録ユーザーからidを取得
       $post->user_id = Auth::user()->id;
       // インスタンスの状態をデータベースに書き込む
       $post->save();
       //「投稿する」をクリックしたら投稿情報表示ページへリダイレクト        
       return redirect()->route('posts.detail', [
           'id' => $post->id,
       ]);
   }

■↑のポイント
・全体の設定
web.phpで記載した、「create」の設定です。
投稿された内容をDBに登録するロジックを記載しています。
・$requestについて
引数に Request クラスのインスタンスを受け入れる記述をします。これによって、Laravelが投稿した内容を渡してくれるようになります。
・全体の流れ
1. インスタンスを作成する。
「$post = new Post();」にてインスタンスを作製しています。
2. 値を代入する。
「$post->title = $request->title;」のように記載することにより、投稿された値を代入しています。
3.  save する
データベースに登録された値をsaveします。
4. リダイレクトする
投稿ボタンを押した後に、詳細ページへリダイレクトしています。


3. PostController@detail

最後に投稿された情報の表示ページの設定です。下記追加します。

    /**
    * 詳細ページ
    */
   public function detail(Post $post)
   {
       return view('posts/detail', [
           'title' => $post->title,
           'content' => $post->content,
           'user_id' => $post->user_id,
       ]);        
   }
■↑のポイント
viewに変数として渡す役目をしています。
「'title' => $post->title,」の場合、viewでは「$title」で表示できます。

以上です。最後にPostController.phpの全体を記載します。

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Post;

class PostController extends Controller
{
   public function showCreateForm()
   {
       return view('posts/create');
   }
   public function create(CreatePost $request)
   {
       // Postモデルのインスタンスを作成する
       $post = new Post();
       // タイトル
       $post->title = $request->title;
       //コンテンツ
       $post->content = $request->content;
       //登録ユーザーからidを取得
       $post->user_id = Auth::user()->id;
       // インスタンスの状態をデータベースに書き込む
       $post->save();
       //「投稿する」をクリックしたら投稿情報表示ページへリダイレクト        
       return redirect()->route('posts.detail', [
           'id' => $post->id,
       ]);
   }
   /**
    * 詳細ページ
    */
   public function detail(Post $post)
   {
       return view('posts/detail', [
           'title' => $post->title,
           'content' => $post->content,
           'user_id' => $post->user_id,
       ]);        
   }
}

以上です。

投稿フォームを作成

次に投稿フォームを作成します。
まずは「resources/views」ディレクトリに、「posts」ディレクトリを作成します。
また、postsディレクトリ配下に「create.blade.php」ファイルを作成します。

次に「create.blade.php」ファイルに下記を記載します。

@extends('layouts.app')
@section('content')
<form method="post" action="{{ route('posts.create') }}" enctype="multipart/form-data">
 @csrf
       <div class="form">
           <div class="form-title">
             <label for="title">タイトル</label> 
             <input class="" name="title" value="{{ old('title') }}">
           </div>
   
           <div class="form-content">
             <label for="content" class="form-content">内容</label> 
             <textarea class="" name="content" cols="50" rows="10">{{ old('content') }}</textarea>        
           </div>
           
           <div class="form-submit">
             <button type="submit">投稿する</button>
           </div>
       </div>
</form>
@endsection
■↑のポイント
@extends('layouts.app')について
デフォルトで用意されている(「/resources/views/layouts/app.blade.php」)を呼び出しています。
@csrfについて
悪意ある投稿から保護する意味で、こちらの記載をします。csrfについて詳しくはこちら

ここまでで、「/post」にアクセスすると下記のような画面が表示されます。

以上で投稿フォームの設定は完了です。


詳細ページ表示用viewを作成

次に詳細ページ表示用のviewを作成します。postsディレクトリ配下に「detail.blade.php」ファイルを作成します。

detail.blade.phpには下記のように記載します。

@extends('layouts.app')
@section('content')
<p>タイトル:{{ $title }}</p>
<p>詳細内容:{{ $content }}</p>
<p>ユーザID:{{ $user_id }}</p>
@endsection
■↑のポイント
変数の取得
$title、$content等、登録された値を取得しています。

投稿された情報をシンプルに表示しています。

簡単ですが以上で表示ようのviewの作成を完了します。


投稿フォームより投稿したデータが「posts」テーブルに格納される

それでは作成したフォームに投稿し、データベースに値が登録されるか確認します。

まずログインします。(「/login」)

※ログイン昨日作成していない場合はこちらを参考に作成してください。

「/post」にアクセスします。

値を記入し、「投稿する」をクリックします。

すると、下記画面が表示されます。

データベースを確認すると、postsテーブルにデータが登録されています。

※PHPMyAdminの図


以上で対応完了です。お疲れ様でした。


今回は説明していないですが、こちらを応用して
・フィールドを必須し、記入されていない場合エラーメッセージを表示する
・ログインユーザ以外には投稿フォームを表示させない

などができるようになります。

↑はおいおい書いていきたいなと思いますので、またよろしくお願いします😊


GitHubリポジトリ

今回作成したソースはGithubにて公開しています。下記リンクよりご確認ください。(lerning-2ブランチです。)

https://github.com/KoushiKagawa/laravel-learning/tree/learning-2

間違いや、もっとこう書いた方が良いよ!といったご指摘はコメント欄かtwitterのDMいただけると喜びます!



読んでいただきありがとうございます。