会員登録の『Facebook認証→入力済みフォーム→改めて登録』処理を実装する

会員登録のページを作っています。
FB認証を必須にしたいので調べつつ作成します。

すでにFBログインに関しては勉強済みですので、これに手を加えます。

- [Laravel5.5でFacebook認証結果をDBに保存する的なログイン機能を実装したい - Qiita](https://qiita.com/ragingalpaca/items/c84b21548871d48f4094)


# 目的
導線としては元々が

```
トップページ
→ログインボタン
→FB認証（→未登録の場合はDBに書き込み）
→トップページ（ログイン状態）
```

だったのを、

```
トップページ
→新規登録ボタン
→新規登録画面
→FB認証（→登録済みならログインする）
→新規登録画面（FBの情報が反映される）
→新規登録ボタン
→DBに書き込み
→トップページ
```

みたいな感じに変えたいです（ぶっちゃけVALUをパクりたい）。


# 具体的に見てみる
変更箇所についてざっとおさらいしてみます。

## FB認証周り
FB認証はSocialiteを利用しています。
FBへのリダイレクトおよびコールバックのどちらも、routes/web.phpでSocialControllerにぶん投げてます。

コールバックの中で登録済みかどうかや、DBへの書き込みなども行なっています。
（こうすればできるなーって感じで実装した部分なので、一般的な処理ではないかもしれません）

というわけで登録済みか判断する処理だけ残して、DBへの書き込みはざっくり削除しました。

DBに書き込まないとなるとどうにかしてデータを持ち越す必要があります。
いろいろやり方を試して、最終的にcompactでviewにFBのユーザーオブジェクトを渡すことにしました。

    return view('auth.callback', compact('me'));

最低限の機能的にはこれだけでもよさそうだったんですが、

1.　リロードするとエラーになる（コールバックで得たFBの情報（消えてる）を読み込もうとするため）
2.　ルーティングを経由すると前述のcompactが効かない
3.　なんかURLに変なパラメータがくっついてるのが嫌

などの理由で他の方法を探すことにしました。
とりあえずFB周りの変更はこれだけ。

## リダイレクトでコールバックから逃れる
FBのコールバック後の画面でリロードするとエラーになるのが嫌だったので、リダイレクトすることにしました。
受け取ったユーザー情報をルーティング経由で渡す方法がわからなかったため、hiddenしたフォームをPOSTして渡しています。

`<body onload="form.XX.submit();">`とか使って自動でPOSTされるようにしつつ、`type="hidden"`にしたinputにデータを必要なだけ埋め込みます。

POST先はまあなんでもいいんでしょうけど、同じルートを使用しました。
スラッシュやドット混じりのルートの指定方法がわからなかったので、適当に名前を付けています。

```php:web.php
// register > FB認証 > callback > register/username
Route::get('auth/facebook/callback', 'Auth\SocialController@handleFacebookProviderCallback');
Route::post('auth/facebook/callback', 'Auth\SocialController@postCallbackRedirect')->name('callback');
Route::get('register/username', 'Auth\SocialController@getRegisterUsername');
Route::post('register/username', 'Auth\SocialController@postRegisterUsername')->name('username');

```

POST先の処理は、withInputをくっつけてリダイレクトするだけです。

```php:SocialController@postCallbackRedirect
    return redirect('register/username')->withInput();
```

- 参考
    - [LaravelのFormでRedirectしたときに値を引き継ぐ | cly7796.net](http://cly7796.net/wp/php/take-over-the-value-when-you-redirect-in-laravel-of-form/)
    - [[laravel] controllerからviewへの変数の受け渡しとその展開方法 - Qiita](https://qiita.com/ryo2132/items/63ced19601b3fa30e6de)
    - [Submit送信以外のときダイアログで確認＆移動する方法 jQuery - Web学び](http://fukuyama.co/beforeunload)


## 改めて登録画面
withInputすることで、遷移先のgetのなかでformの情報が取得できます。
なのでこれを今度こそcompactでviewに渡してやります。

```php:SocialController@getRegisterUsername
        // post内容を取得
        $postdata = Session::get('_old_input');

        return view('auth.username', compact('postdata'));
```

## あとは普通に？POSTしたデータを書き込む
viewに渡したあとはごく普通のformなので、受け取ったデータを書き込んで、適当なところにリダイレクトしてやります。

### っていうかリダイレクトしたあと
リロードすると結局データ消えるんですね……。
とするとPOSTじゃなくて別の方法で管理した方がいいのかな？
別の方法に心当たりはないんですけど。セッションとか？

というわけでリロードの制御（というか『データ消えるけど離脱する？』的なメッセージ）を入れました。
これが結局必要になるなら、リダイレクト要らなかったかもと思わないでもないですが、URLになんか付いてるのも気になってたのでよしとします。

## beforeunloadの制御
といいつつ、リロード制御で微妙に詰まってます。
Safariだと何も出てこない。
そもそも動かないサンプルも見かけたし……。

とりあえずjQueryのやり方で想定通りの動きができたのでこれでよしとします。。

- 参考
    - [Submit送信以外のときダイアログで確認＆移動する方法 jQuery - Web学び](http://fukuyama.co/beforeunload)
    - [beforeunloadにカスタムメッセージを表示できなくなっていた - Qiita](https://qiita.com/nantekkotai/items/9a6e2c98ed704934ab47)

### Safariの謎の挙動
リロードすると（フォームの内容は消えるけど）他のページへの遷移は確認メッセージが出るようです。
なんだこれ……。


# Safariは置いてきた
検討はしたがハッキリ言って僕の知識では対応できない（ｷﾘｯ

というわけでできたことにして終わりにします