【laravel】ログインの実装

# 概要
laravelのユーザー認証には以下のような機能があるため備忘録として記事にします。
使用したい機能が思いつき次第に追記する可能性がります。

・ユーザーの登録
・ユーザーのログインとログアウト
・ログインしていないユーザーからのアクセス制限


# ログイン機能の準備
Laravel 6.0からログイン機能は`laravel/ui`という別パッケージとして管理されるようになりました。
そのため、まずはログイン機能の実装から始めます。
実装と聞くとややこしく感じますが数行のコマンドを記述するだけです。
以下の手順でログイン機能を実装し、トップ画面の右上に`LOGIN`と`REGISTER`のリンクが作成できていれば完了です。


## laravel/uiのインストール
ログイン機能のパッケージである`laravel/ui`はcomposerでインストールします。
また、laravel6.*では`laravel/ui`のバージョンを指定してインストールする必要があります。

```:コマンド
composer require laravel/ui ^1.* --dev
```

## auth関連のファイルを生成
インストールした`laravel/ui`によりAuth関連のファイルを生成します。
これはartisanの`ui`コマンドで実行します。
例ではvueを指定していますが、reactでも実装できます。

`ui`コマンドにより、viewsとControllersにAuth関連のファイルが生成されます。

```:コマンド
php artisan ui vue --auth
```

```:ディレクトリ
resources
├─ views
|  ├─ auth  ※
|  |  ├─ passwords
|  |  |  └─ ... 3個
|  |  └─ ... 3個
|  ├─ layouts
|  |  └─ app.blade.php  ※
|  ├─ home.blade.php  ※
```

```:ディレクトリ
app
├─ Http
|  ├─ Controllers
|  |  └─ Auth  ※
|  |  |  └─ ... 5個
|  |  ├─ HomeContoroller.php
```

# フロントエンドのモジュールを実装する
上記作業はlaravelの設定のみで、フロント側のモジュールが実装されていません。
ログイン機能を使用するだけなら必要ありませんが、せっかくなので見た目も整えてもらいます。


## nodejsのインストール
nodejsがなければインストールします。
以下からダウンロードページへリンクします。
無難に推奨版をインストールしました。
記事作成時は12.16.3LTSが推奨版でした。

[Node.js]
(https://nodejs.org/ja/)


## パッケージのインストールとビルド
実装に必要なパッケージをインストールします。

```:コマンド（インストール）
npm install
```

```:コマンド（ビルド）
npm run dev

// 本番環境なら
npm run production
```


## 補足
以下の環境ではビルド時にエラーが発生するため、パッケージを指定してインストールし直しました。

● 実行環境
laravel 6.18
PHP 7.3
nodejs 12.16
npm 6.14

```php:
npm uninstall --save-dev sass-loader
npm install --save-dev sass-loader@7.1.0
```


# データベースの作成
laravelプロジェクトを作成した段階で`users`と`password_resets`のマイグレーションファイルが用意されているため、編集してマイグレーションを実行します。
マイグレーションとシーディングについては以下をご参考ください。
[【laravel】マイグレーション]
(https://qiita.com/gone0021/items/5cec0c945b41c00441cc)
[【laravel】シーディングによるレコードの追加]
(https://qiita.com/gone0021/items/fe2e9deffddf8b4b0114)


# ログインのチェック
ここではログインのチェックを実行して、成功していればテンプレートの内容を表示するという例を書きます。

まず、コントローラーで現在ログインされているユーザーを取得してテンプレートに渡します。
現在ログインされているユーザーを取得するメソッドがAuthファサードの`user()`です。
テンプレートではログインしていればtrueを返すAuthの`check`というメソッドでログインしているか否かを判断します。

これらの作業はAuthファサードを使用するため`Illuminate\Support\Facades\Auth`をuseします。


```php:Contoller
use Illuminate\Support\Facades\Auth;
```

```php:Contoller
public function index(Request $request)
{
  $user = Auth::user();
  $param = ['user'=>$user];
  return view('hello.index', $param);
}
```

```php:view

@if (Auth::check())
  <p>ようこそ{{ $user->name }}さん</p>
  // ... 表示処理
@esle
  <p>ログインしてください</p>
  <a href="/login">ログイン</a>
@endif
```

# ページの保護
ログインしていない状態でアクセスしたらログインページへリダイレクトするための設定です。
特定のページだけ保護する方法と全てのページを保護する2つの方法があります。

## 特定ページの保護
ルーティングの設定でAuthミドルウェアを指定すれば、指定したページにログインによる保護を実装できます。
AuthミドルウェアはHTTPカーネルで登録済みのため指定するだけで使用できます。

```php:web
Route::get('sample', 'SampleController@index')->middleware('auth');
```

## 全ページの保護
コントローラーにコンストラクタを記述することで全てのページに保護を実装します。

```php:Contoller
public function __construct()
{
  $this->middleware('auth');
}
```


# 独自にログインを実装する
Authファサードの`attempt()`でログイン情報をチェックします。
`attempt()`は引数にemailとpasswodの連想配列が渡されてログインのチェックを行い、成功なら`true`を返し失敗なら`false`を返すメソッドです。
ここではコントローラーで記述しましたが、上記の`ログインのチェック`で使用したAuthファサードの`check()`と同じような処理です。


```php:Contoller
public function postAuth(Request $request)
{
  $credentials = $request->only('email', 'password');
  if (Auth::attempt($credentials) {
    $msg = 'ようこそ' . $user->name . 'さん';
  } else {
    $msg = 'ログインに失敗しました';
  }
  return view('hello.auth', ['message' => $msg]);
}
```


# 参考
[Laravel 6.x 認証]
(https://readouble.com/laravel/6.x/ja/authentication.html)
[Laravel6.x以降でログイン機能をインストールする方法]
(https://blog.capilano-fw.com/?p=4576)
[Laravel6でVueを使おうとnpm run watchをするとエラーが出る]
(https://teratail.com/questions/242618)