Laravelで掲示板を作ってみる

[前回の記事](https://qiita.com/qwertyuiopngsdfg/items/90e71322abbb425d1fd8)を見てくれた人が少しいたので
今回は前回作った掲示板をLaravelを使って作ってみる記事です。

ソースコードを全部みたい奇特な方は僕の[Github](https://github.com/qwertyuiopngsdfg/Laravel_BBS)を見てください。

前回の記事から来てくれた人もいるかもしれませんが
Laravelの入門サイトに目を通した人向けです。
今回もLaravelの導入部分や基本的な文法についての説明はしません。
1から10まで説明しても良いんですが、非常に長くなるし、悩みどころです。
お父さんが背中で語ってくれたように、僕はLaravelで掲示板を少しだけ先に作った先輩としてコードで語ることにします。

私もフレームワーク自体今回が初めてなのですが
なるべくコードを読んだらわかるように心がけてます。が、読んでもよくわからない所はコメントしてくれれば
気付いたら一緒に悩みます。

Laravelを使ってたことがある人ももっとこうした方が良いなどがあれば是非コメントに。すぐ修正します。

#環境
Laravel 5.5.39
PHP 7.0.28
mysql 14.14 

#Config

今回も前回と同様に
MySQLでbbs_usersというデータベースとdbuserというユーザーを用意しました。
passwordはsecretにしました。
envファイルに自分のデータベースの情報を設定してあげます。

```/.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=bbs_users
DB_USERNAME=dbuser
DB_PASSWORD=secret
```


Userモデルとmigrationファイルを作成しましょう
--migrationの部分は-mに短縮して書くこともできます。

```
$ php artisan make:model User --migration 
```

migrationファイルにテーブルの設定を書き込みます

```database/migrations/date__create_users_table.php
//migrationファイル
Schema::create('users', function (Blueprint $table) {
  $table->increments('id');
  $table->string('name', 25)->default('名無しさん');
  $table->text('body');
  $table->string('password');
  $table->timestamps();
});
```

artisanコマンドでusersテーブルが作成できます。

```
php artisan migrate
```

User.phpに下記を追加することで、書き込み可能になるわけです。

```app/User.php
//Userモデル
protected $fillable = [
        'name', 'body', 'password'
     ];
```


これで設定はあらかた終わりです。


#routes

```routes/web.pjp
Route::get('/', 'PagesController@index');
Route::view('/create', 'UsersController@create');
Route::post('/posts', 'UsersController@save');
Route::get('/users/{user}', 'PagesController@confirm');
Route::post('/delete', 'UsersController@delete' );
```
ルートの設定です。
難しく考えずにこのURLにアクセスされたら、Controller@メソッドが実行されるんだなくらいに考えたら良いです。
Controller@メソッドはこれから書いていきます

#Controller

次はコントローラーを作成します。
app/Http/Controllers/の中にファイルを作ってくれます。

Userコントローラーに投稿や削除などの処理を
Pagesコントローラーにはユーザーの情報を取得して表示する処理を書いていくことにしましょう

```
$ php artisan make:controller UsersController
$ php artisan make:controller PagesController

```


###UsersController
```app/Http/Controllers/UsersController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;
use App\Http\Requests\UsersRequest;
use Illuminate\Support\Facades\Hash;

class UsersController extends Controller
{
    
    public function save(UsersRequest $request) { //登録処理
        $user = new User();
        if ($request->name) $user->name = $request->name;
        $user->password = Hash::make($request->password); //password_hashみたいなの
        $user->body = $request->body;
        $user->save();
        return redirect('/');
    }

    public function delete(Request $request) { //削除処理
        $user = User::findOrFail($request->id);
        if (Hash::check($request->password , $user->password)) { //password_verifyみたいなの
            User::destroy($user->id);
            return redirect('/');
        }
            $error = 'The password is incorrect';
            return view('confirm', ['error' => $error])->with('user', $user);
    }

}

```

###PagesController

```app/Http/Controllers/PagesController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;

class PagesController extends Controller
{

    public function index() {
        $users = User::latest()->get();
        return view('index', ['users' => $users]);
    }

    public function confirm(User $user) {
        return view('confirm', ['user' => $user]);
    }

}

```

色々と便利なのが出てきました。
ユーザーの登録や削除がとても短い行でセキュアにかけます。
save()のところでif文を使ってるのはユーザーから名前入力が無いときに
エラーが起こるか、nullや空文字を許可してもデフォルトの名無しさんが無視されてそのまま空文字が入ってしまうからです。
入力が無いときはnameを何も操作しないことで、ちゃんとデフォルトで設定した名無しさんになってくれます。

ユーザーから送られてきたPOSTをバリデーションとかしないでそのまま受け取るときはRequestで受け取れます。
UsersRequestってのは次に書いていきます。

#Validetion

名前は決まってるわけじゃないのでHogeRequestでもなんでも

```
php artisan make:request UsersRequest
```

これでApp/Httpの中にRequests/UsersRequest.phpができます。

```app/Http/Requests/UsersRequest.php
class UsersRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'body' => 'required|max:255',
            'password' => 'required|min:8'
        ];
    }

     /**
     * Get the error message that apply to the request.
     *
     * @return array
     */
    public function messages(){
        return [
            'body.required' => 'Please enter body',
            'password.required' => 'Please enter password',
            'password.min' => 'Must higher than 8 characters in length'
        ];
    }
    
}
```
作ったばかりだとクラス名がPostsRequestだったと思います。
UsersRequestなんて無いよと言われて困ったので気をつけてください。

ここまででバックエンド側の処理は終了です。

#views

###default.blade.php

```resources/views/layouts/default.blade.php
<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="utf-8">
		<title>@yield('title')</title>
		<link rel="stylesheet" href="/css/styles.css">
	</head>
	<body>
		<div id="header">
			@yield('header')
			<h1>掲示板</h1>
		</div><!-- header -->
		<div id="main">
			@yield('content')
		</div><!-- main -->
	</body>
</html>
```
###index.blade.php

```resources/views/index.blade.php

@extends('layouts.default')

@section('title', '掲示板')

@section('header')
	<p>現在の投稿<span>{{ $users->count() }}</span>件</p>
	<h2><a href="{{ url('/create') }}">投稿する</a></h2>
@endsection

@section('content')
	<dl>
	@forelse ($users as $user)
	<div class="posts">
		<dt>
			<span>1</span><span>名前：{{ $user->name }}</span>
			<span>{{ $user->created_at }}</span><br>
		</dt>
		<dd>
			{!! nl2br(e($user->body)) !!}
			<a href="{{ action('PagesController@confirm', $user->id) }}">削除</a>
		</dd>
	</div><!-- posts -->
	@empty
		<p>まだ投稿はありません。</p>
	@endforelse
	</dl>
	@if ($users->count() > 5)
	<button id="load_more">全件表示</button>
	@endif
@endsection

```

###create.blade.php

```resources/views/create.blade.php
@extends('layouts.default')

@section('title', '新規投稿')

@section('content')
    <form action="{{ url('/posts') }}" method="post">
    {{ csrf_field() }}
        <p>
            <input type="text" name="name" value="{{ old('name') }}" id="name" placeholder="enter name">
        </p>
        <p>
            <input type="password" name="password" placeholder="enter password">
        </p>
        @if ($errors->has('password'))
            <span class="error">{{ $errors->first('password') }}</span>
        @endif
        <p>
            <textarea name="body" rows="8" cols="40" value="{{ old('body') }}" placeholder="enter comment"></textarea>
        </p>
        @if ($errors->has('body'))
            <span class="error">{{ $errors->first('body') }}</span>
        @endif
        <p>
            <input type="submit" value="submit">
        </p>
    </form>
@endsection
```

###confirm.blade.php

```resources/views/confirm.blade.php
@extends('layouts.default')

@section('title', '削除画面')

@section('content')
    <h1>本当にこの記事を削除しますか？</h1>
    <dl>
        <dt>
            <span>1</span><span>名前：{{ $user->name }}</span>
            <span>{{ $user->created_at }}</span><br>
        </dt>
        <dd>
            {{ $user->body }}
        </dd>
    </dl>
    <form action="{{ url('/delete') }}" method="post">
        {{ csrf_field() }}
            <p>
                <input type="password" name="password" placeholder="enter password">
                <input type="hidden" name="id" value="{{ $user->id }}">
            </p>
            <p>
                @if (isset($error))
                <span class="error">{{ $error }}</span>
                @endif
            </p>
                <input type="submit" value="submit">
        </form>
@endsection
```

なんかフレームワークっぽいですよね。
勝手にエスケープしてくれて親切です。まだそのくらいの認識です。

#終わり

説明が雑な気がしますが、どうなんでしょうか。
[github](https://github.com/qwertyuiopngsdfg/Laravel_BBS)にソースコードが載ってます。

正直フレームワーク触ろうかなレベルの人はこれ読む時間があれば自分でできる気がしてきました。
どこまでが初心者でどこからが中級車なんでしょうか。
作ってみたシリーズはそろそろ潮時な気がします。
また、何か思いついたら会いましょう。