Laravelの基本はこちらから学べます

Laravel6×MAMPで掲示板を作ろう③




Post投稿画面を作成する

新規投稿ページを作成する

投稿一覧画面に新規追加ボタンを記入しましょう。

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 text-center">
                <div class="card-header">
                    投稿一覧
                </div>
                <div class="card-body">
                    <h5 class="card-title">1回目の投稿</h5>
                    <p class="card-text">油そばは春日亭も好きですが、kirinjiが一番好きです</p>
                    <a href="#" class="btn btn-primary">詳細へ</a>
                </div>
                <div class="card-footer text-muted">
                    2日前
                </div>
            </div>
        </div>

        ***<div class="col-md-2">
            <a href="{{ route('posts.create') }}" class="btn btn-primary">新規投稿</a>
        </div>***

    </div>
</div>
@endsection

新規投稿のaタグのリンク先を「posts.create」にしました。

試しにボタンを押すと、

/posts/create に飛べましたね。

次に

PostController.phpをひらきましょう。

新規投稿画面を作成するので、「public function create」に書き込んでいきます。

public function create()
    {
        return view('posts.create'); →追加(postsディレクトリのcreate.blade.phpという意味)
    }

同時にcreate.blade.phpも編集していきましょう。Bootstrapのformを改造して使います。

Forms

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <form action="{{ route('posts.store') }}" method="POST">
            {{csrf_field()}}
                <div class="form-group">
                    <label>タイトル</label>
                    <input type="text" class="form-control" placeholder="タイトルを入力して下さい" name="title">
                </div>
                <div class="form-group">
                    <label>内容</label>
                    <textarea class="form-control" placeholder="内容" rows="5" name="body"></textarea>
                </div>
                <button type="submit" class="btn btn-primary">作成する</button>
            </form>
        </div>
    </div>
</div>
@endsection

formタグのアクション先を「posts.store」にし、methodはPOST!!!

csrf_fieldを忘れずに記入しましょう!!(csrf保護については下の記事を流し見することをお勧めします。)

Laravel 6.x CSRF保護

バリデーションを行う

保存したい内容を入力し、「作成するボタン」を押すことで PostControllerのstoreメソッドまで送ることができるようになりました。

確認をしてみましょう。ここで使うのはdd()というデバックです。

public function store(Request $request)
    {
        dd($request); →追加
    }

このメソッドでは「$request」を受け取っています。この中には、「create.blade」で入力した値が入っているはずなので、ddで中身を確認してみましょう。

作成ボタンを押すと。

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/58e33dc6-0502-4a9e-b51e-f8da25b7ef70/_2020-04-15_16.12.52.png

ちゃんと入ってきていますね。

次にやることはバリデーションです。

「バリデーション」では入力された内容をチェックして妥当性があるかを確認する作業です。

例えば、blogのタイトルは3文字以上がいいよね….とかです。

php artisan make:request PostRequest

すると、Http Request 配下にPost.phpが作成されるます。

こちらにいろいろなルール付をすることができます。

public function authorize()
    {
        return true; →trueに変更
    }


public function rules()
    {
        return [
            'title' => 'required|max:20',
        'body'  => 'required',
        ];
    }


public function messages()
{
    return [
        'title.required' => 'タイトルは必須です。',
	'title.max'      => 'タイトルは20文字以内で記入してください。',
        'body.required'  => '内容は必須です。',
    ];
}

次にこの作成したルールを適用させます。

PostController.phpを開きましょう。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\PostRequest; →追加




public function store(PostRequest $request) →PostRequestを適用
    {
        dd($request);
    }

そして先ほど設定したバリデーションメッセージを表示できるように記載しましょう。

create.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            ***@if ($errors->any())
                <div class="alert alert-danger">
                    <ul>
                        @foreach ($errors->all() as $error)
                            <li>{{ $error }}</li>
                        @endforeach
                    </ul>
                </div>
            @endif***
            <form action="{{ route('posts.store') }}" method="POST">
            {{csrf_field()}}
                <div class="form-group">
                    <label>タイトル</label>
                    <input type="text" class="form-control" placeholder="タイトルを入力して下さい" name="title">
                </div>
                <div class="form-group">
                    <label>内容</label>
                    <textarea class="form-control" placeholder="内容" rows="5" name="body"></textarea>
                </div>
                <button type="submit" class="btn btn-primary">作成する</button>
            </form>
        </div>
    </div>
</div>
@endsection

エラーが返ってきて表示ができるようになりました!確認してみましょう。

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a355a1cc-bcb4-4249-8962-5fab72fc46ee/_2020-04-15_16.41.39.png

タイトル、内容を入れずに作成するボタンを入力すると、エラーが出るようになりました!!

下のドキュメントに目を通しましょう。

Laravel 6.x バリデーション

modelの設定(fillable)

modelにfillableを設定しましょう。

app 配下 Post.php

class Post extends Model
{
    protected $fillable = ['title', 'body'];
}

app 配下 Comment.php

class Comment extends Model
{
    protected $fillable = ['body'];
}

のように変更しましょう。

$fillableに設定したもの以外のカラムはユーザーが変更できないようにできます。

例えば、IDや今回は作成しませんがadminなどの情報を、ユーザーに変更されてしまうとサイトの脆弱性につながります。それらを回避するために、モデルにユーザーの入力によって変更できるカラムを指定します。

データベースに保存できるようにする。

入力した内容をチェックすることができるようになりましたので、次はデータベースに保存できるようにしていきます。

PostController.php

use Illuminate\Http\Request;
use App\Http\Requests\PostRequest;
use App\Post;
use Auth;


class PostController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }


--省略---

	public function store(PostRequest $request)
    {
        ***$post = new Post; //インスタンスを作成

        $post -> title    = $request -> title; //ユーザー入力のtitleを代入
        $post -> body     = $request -> body; //ユーザー入力のbodyを代入
        $post -> user_id  = Auth::id(); //ログイン中のユーザーidを代入

        $post -> save(); //保存してあげましょう
        
        return redirect()->route('posts.index');
    }

ここでは「use」するものを2つ増やし、「function」を1つ追加、「store function」の中身を追加しました。

  1. use App\Postと use Auth
    1. use AppはこのcontrollerでPostモデルを使うよという意味。
    2. use Authは
  2. function __construct()ではミドルウェアをこのコントローラーに付与しています。 ログインしていないユーザーはこのコントローラーのメソッドを1つも動かせなくなりました🙌 ログインしていない状態で、「/posts」にアクセスするとログイン画面に飛ばされます。
  3. store について詳しくみていきます。 ユーザーの入力値($request)、ログイン中のユーザーIDを代入し保存している。

DBから一覧ページに表示する。

一覧ページはまだ固定の投稿しか表示できていません。

今回はDBから引っ張ってきた投稿を一覧で表示できるようにしましょう。

まずはコントローラーでデータベースからデータを取得しましょう。

PostController.php

public function index()
    {
	$posts = Post::all();
        return view('posts.index', compact('posts'));
        //return view('posts.index');
    }

ここでは、Postモデルを通し、postsテーブルからデータを全取得(all)。$postsという変数に代入しました。

compact関数というものを用いて、$postsをpostsのindexに渡しています。

index.php にて

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card text-center">
                <div class="card-header">
                    投稿一覧
                </div>
                @foreach ($posts as $post)
                <div class="card-body">
                    <h5 class="card-title">タイトル:{{ $post->title }}</h5>
                    <p class="card-text">***内容:{{ $post->body }}</p>
                    <a href="#" class="btn btn-primary">詳細へ</a>
                </div>
                <div class="card-footer text-muted">
                    投稿日時:{{ $post->created_at }}
                </div>
                @endforeach
            </div>
        </div>
        <div class="col-md-2">
            <a href="{{ route('posts.create') }}" class="btn btn-primary">新規投稿</a>
        </div>
    </div>
</div>
@endsection

解説。$postsを1つずつforeachで回すことで、全件の内容を表示する。

@foreach ($posts as $post) → $postsの中身を$postとして回す。

  <h5 class="card-title">タイトル:{{ $post->title }}</h5>
  <p class="card-text">内容:{{ $post->body }}</p>

@endforeach

ここで一覧ページをみてみましょう。

一欄ページに全てのpostを表示することができるようになりました。

今回はここまで!お疲れ様でした。




コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です