Laravelで作られた掲示板に機能を追加する②


[Laravelで作られた掲示板に機能を追加する①](https://qiita.com/YKhojo/items/548d19d3f98e32c292e3)の続きです。

## 目標

1. breezeを導入しログイン機能を実装
2. ログイン/非ログインで表示を変更する
3. リダイレクト先の変更
4. ログアウト機能の実装

<br>

## 1. breezeを導入しログイン機能を実装

[このサイト](https://php-junkie.net/framework/laravel/breeze/)を参考にし、breezeをインストールします。

```
$ composer require laravel/breeze --dev
```

---

備忘録的なエラー記録
`php artisan breeze:install`すると
`Please execute the "npm install && npm run dev" command to build your assets.`というエラーがでるので、
`npm install && npm run dev`してみると
`bash: npm: command not found`がでたので

---

```
$ apt-get install -y npm
```

してみたら色々インストールされたので

```
$ npm install && npm run dev
```

で、インストール成功すると下記が表示されます。

![スクリーンショット (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485388/dbcd1d9a-c372-d70e-9b63-a58aa0497dcc.png)

```
$ node -v
$ npm -v
```

で両方ともバージョンが表示され、インストールされていることが確認できました。

http://localhost:8000/
にアクセスすると右上にLogin Registerが表示されていました。やったね。

<br>

## ルーティングの復旧

breezeをインストールするとweb.phpが上書きされていたので、必要な部分のみ復旧します。

```routes\web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostsController;
use App\Http\Controllers\CommentsController;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

require __DIR__.'/auth.php';


Route::resource('/bbs', PostsController::class)->parameter('bbs', 'post')->only([
    'index', 'show', 'create', 'store', 'edit', 'update', 'destroy'
]);

Route::resource('/comment', CommentsController::class)->only([
    'store'
]);
```

<br>

## viewファイルの編集

localhostにアクセスするとLogin Registerが表示されているので、それを/bbsにアクセスした時にも表示するようにします。
赤枠の部分が、LaravelPjtBBSにあればいいなという感じです。

![スクリーンショット (31).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485388/ae213017-6f09-5516-0f67-41b7dc60cec7.png)

```resources\views\layout\bbsheader.blade.php
    <div class="container">
        <a class="navbar-brand" href="{{ url('/bbs/') }}">LaravelPjt BBS</a>
    </div>

　　　↓　変更　↓

    <div class="container">
        <a class="navbar-brand" href="{{ url('/bbs/') }}">LaravelPjt BBS</a>

        @if (Route::has('login'))
            <div class="navbar-brand sm:block">
                @auth
                    <div>{{ Auth::user()->name }}</div>
                @else
                    <a href="{{ route('login') }}" class="text-sm text-gray-700 underline">Log in</a>
                    @if (Route::has('register'))
                        <a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 underline">Register</a>
                    @endif
                @endauth
            </div>
        @endif

    </div>
```

resources\views\welcome.blade.phpをほぼコピペしています。
cssは好みでカスタマイズすればいいので、とりあえずclassはコピペしたまんまを使います。

Log inかRegisterでログインした場合はdashboardでログアウトをして、URLを/dashboardから/bbsに変更します。
右上にLog in　Registerが表示されているはずです。

![スクリーンショット (33) - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485388/aa8b4a7e-433b-fcfe-5654-88867334fb94.png)

<br>

## 2. ログイン/非ログインで表示を変更する

次に非ログイン時は、新規投稿や編集をさせないように該当箇所を表示しないようにします。

- /bbsのページ
  - 新規作成ボタンを非表示
  - 編集ボタンを非表示
  - 削除ボタンを非表示
- 詳細ページ
  - 編集ボタンを非表示
  - 削除ボタンを非表示
  - コメント入力欄を非表示

```resources\views\bbs\index.blade.php
（略）
// 新規作成ボタンを非表示
@section('content')
<div class="mt-4 mb-4">
    <a href="{{ route('bbs.create') }}" class="btn btn-primary">
        投稿の新規作成
    </a>
</div>
@if (session('poststatus'))
    <div class="alert alert-success mt-4 mb-4">
        {{ session('poststatus')}}
    </div>
@endif

↓　変更　↓

@section('content')
    @if (Route::has('login'))
        @auth
            <div class="mt-4 mb-4">
                <a href="{{ route('bbs.create') }}" class="btn btn-primary">
                    投稿の新規作成
                </a>
            </div>
            @if (session('poststatus'))
                <div class="alert alert-success mt-4 mb-4">
                    {{ session('poststatus')}}
                </div>
            @endif
        @endauth
    @endif

（略）

// 編集と削除ボタンを非表示
                    <p><a href="{{ action('App\Http\Controllers\PostsController@edit', $post->id) }}" class="btn btn-info btn-sm">編集</a></p>
                    <p>
                        <form method="POST" action="{{ action('App\Http\Controllers\PostsController@destroy', $post->id) }}">
                            @csrf
                            @method('DELETE')
                            <button class="btn btn-danger btn-sm">削除</button>
                        </form>
                    </p>

　　　　　　　　　　↓　変更　↓

                    @if (Route::has('login'))
                        @auth
                            <p><a href="{{ action('App\Http\Controllers\PostsController@edit', $post->id) }}" class="btn btn-info btn-sm">編集</a></p>
                            <p>
                                <form method="POST" action="{{ action('App\Http\Controllers\PostsController@destroy', $post->id) }}">
                                    @csrf
                                    @if (Route::has('login'))
                                        @auth
                                            @method('DELETE')![スクリーンショット (33) - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485388/7c3a35e6-832b-4a2d-790a-98c9d9b8a834.png)

                                            <button class="btn btn-danger btn-sm">削除</button>
                                        @else
                                        @endauth
                                    @endif
                                </form>
                            </p>
                        @endauth
                    @endif
```

これで画像のように新規作成や編集と削除は表示されなくなったはずです。
![スクリーンショット (33).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485388/1f517131-1e6b-725b-1d73-b0747b35c455.png)



<br>

```resources\views\bbs\show.blade.php
// 編集と削除ボタンを非表示
（略）
         <!-- 編集・編集ボタン -->
        <div class="mb-4 text-right">
            <a href="{{ action('App\Http\Controllers\PostsController@edit', $post->id) }}" class="btn btn-info">
            編集する
            </a>
        
            <form
                style="display: inline-block;"
                method="POST"
                action="{{ action('App\Http\Controllers\PostsController@destroy', $post->id) }}"
            >
                @csrf
                @method('DELETE')
                
                <button class="btn btn-danger">削除する</button>
            </form>
        </div>

　　　　↓　変更　↓

         <!-- 編集・編集ボタン -->
        @if (Route::has('login'))
            @auth
                <div class="mb-4 text-right">
                    <a href="{{ action('App\Http\Controllers\PostsController@edit', $post->id) }}" class="btn btn-info">
                    編集する
                    </a>
                
                    <form
                        style="display: inline-block;"
                        method="POST"
                        action="{{ action('App\Http\Controllers\PostsController@destroy', $post->id) }}"
                    >
                        @csrf
                        @method('DELETE')
                        
                        <button class="btn btn-danger">削除する</button>
                    </form>
                </div>
                @else
            @endauth
        @endif


// コメント入力欄を非表示
　　　　（略）
        <form class="mb-4" method="POST" action="{{ route('comment.store') }}">
            @csrf
        
            <input
                name="post_id"
                type="hidden"
                value="{{ $post->id }}"
            >
        
            <div class="form-group">
                <label for="subject">
                名前
               （略）
                コメントする
                </button>
            </div>
        </form>

　　　　↓　変更　↓

        @if (Route::has('login'))
            @auth
                <form class="mb-4" method="POST" action="{{ route('comment.store') }}">
                    @csrf
                
                    <input
                        name="post_id"
                        type="hidden"
                        value="{{ $post->id }}"
                    >
                
                    <div class="form-group">
                        <label for="subject">
                        名前
                       （略）
                        コメントする
                        </button>
                    </div>
                </form>
            @endauth
        @endif
```

長々と書きましたが、結局は下記のようにif文で囲っただけです。

```
        @if (Route::has('login'))
            @auth
　　　　　　　ログイン時に表示したい内容
            @endauth
        @endif
```

<br>

## 3. リダイレクトの変更

ログインするとdashboardに飛ばされるので、bbsに飛ぶように修正します。
ついでいログアウトのリダイレクト先もbbsに変更します。

```app\Http\Controllers\Auth\AuthenticatedSessionController.php
    public function destroy(Request $request)
    {
        Auth::guard('web')->logout();

        $request->session()->invalidate();

        $request->session()->regenerateToken();

        return redirect('/bbs'); // ←　return redirect('/')から変更
    } 
```

```app\Http\Controllers\Auth\AuthenticatedSessionController.php
class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to the "home" route for your application.
     *
     * This is used by Laravel authentication to redirect users after login.
     *
     * @var string
     */
    public const HOME = '/bbs'; // ←　return redirect('/dashboard')から変更
```

<br>

## 4. ログアウト機能の実装

Registerから新規登録（既にアカウントを作った方はLog in)してください。
ログインすると画面右上に名前が表示されているます。
今から画像のように名前の右側にLog Outリンクを作ります。
（本当はdashboardのように名前をクリックするとlog outが表示されるようにしたかったのですが、上手くいきませんでした）

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485388/9294cc94-5e67-4b7e-09fa-82695aabad1f.png)

---

### パターン１

formのclass="mb-0"はformがmargin bottomを持っていてレイアウトが崩れたので、それを打ち消すためです。

```resources\views\layout\bbsheader.blade.php
        @if (Route::has('login'))
            <div class="navbar-brand sm:block">
                @auth
                    <div class="row">
                        <div class="text-sm text-gray-700 underline">{{ Auth::user()->name }}</div>
                        <div class="ml-4 text-sm text-gray-700 underline">
                           <form class="mb-0" method="POST" action="{{ route('logout') }}">
                                @csrf
                                <a href="route('logout')" onclick="event.preventDefault(); this.closest('form').submit();">
                                    {{ __('Log out') }}
                                </a>
                            </form>
                        </div>

                    </div>
                @else
```

ちなみに上記のコードはdashboard（というかnavigation）のlog out部分（下記）を参考にして書き直しました。

```resources\views\layouts\navigation.blade.php
                        <!-- Authentication -->
                        <form method="POST" action="{{ route('logout') }}">
                            @csrf
                            <x-dropdown-link :href="route('logout')"
                                    onclick="event.preventDefault();
                                                this.closest('form').submit();">
                                {{ __('Log Out') }}
                            </x-dropdown-link>
                        </form>
```

---

### パターン２

多分よろしくない書き方なのですが、こういう書き方でも動作したので記載しておきます。


```resources\views\layout\bbsheader.blade.php
        @if (Route::has('login'))
            <div class="navbar-brand sm:block">
                @auth
                    <div class="row">
                        <div class="text-sm text-gray-700 underline">{{ Auth::user()->name }}</div>
                        <div class="ml-4 text-sm text-gray-700 underline"><a href="{{ route('logout') }}">Log out</a></div>

　　　　　　　　　　　　　// こちらでも動きます
                        <!-- <div class="ml-4 text-sm text-gray-700 underline">
                            @csrf
                            <form class="mb-0" method="POST" action="{{ route('logout') }}">
                                <a href="{{ route('logout') }} ">Log out</a>
                            </form> 
                        </div> -->
                    
                    </div>
                @else

```

bladeの変更だけだと`The GET method is not supported for this route. Supported methods: POST.`が出るので、ルーティングを追記します。
Laravel 5.xの頃から下記の修正方法があったようです。

```routes\auth.php
Route::get('/logout', [AuthenticatedSessionController::class, 'destroy']); // ←Route::postの上に追記
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])
                ->middleware('auth')
                ->name('logout');
```

参考サイト
https://qiita.com/kuroudoart/items/44eca2150f102ba7fdb4
https://dev.classmethod.jp/articles/try-using-auth0-with-php-laravel/

---

これでBreezeを用いたログイン機能が出来ました。

<br>

---
続きは、[Laravelで作られた掲示板に機能を追加する③](https://qiita.com/YKhojo/items/3e80c50d75cfdc72eee1)にて！