LoginSignup
3
0

More than 5 years have passed since last update.

Laravel5.5でFacebook認証結果をDBに保存する的なログイン機能を実装したい

Last updated at Posted at 2018-01-01

参考資料

今回はこれをなぞります。
以前は理解できずに挫折しましたが、今なら理解できるはず……!
古い情報なのでバージョンは5.5ではないっぽいです。

前段

これで作成中のアプリに機能を追加していきます。

FacebookSDKのインストール(※)

結論からいうとこの手順は必要ありません。

仮想環境
composer require facebook/php-sdk

インストールはできたんですが、なんか怒られました。

Package facebook/php-sdk is abandoned, you should avoid using it. Use facebook/graph-sdk instead.

php-sdkというのはもう使われてないのでgraph-sdkを使ってねとのこと。
グラフ……?って気分になりますが本当なんでしょうか。
とりあえずそっちもインストールしておくことにします。

Facebookアプリの作成

これは済んでいるのでスルー。
ドメインとコールバックURLの指定をしっかりしましょう。
FB側の認証ってどうすればいいんだろう、ひたすらにめんどい

configファイルの作成

app/config/facebook.phpとありますが、Laravel5.5だとconfig/facebook.phpですね。

DBの作成

これもフォルダ配置が微妙に違います。
usersはすでに作成しているので、適当に項目を変更しました。
photoを追加しただけかな。

datebase/migrations/create_users_table.php
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('email')->unique();
            $table->string('photo');
            $table->string('name');
            $table->string('password');
            $table->string('lang')->default('en');
            $table->string('timezone')->default('UTC');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }

profilesは作成します。
あ、migrate:makeじゃなくてmake:migrationみたいです。
なんか前にもやった気がするこれ。
(ていうかLaravelのバージョンがそもそも違うのを参考にしているという……)

$ php artisan make:migration create_profiles_table
Created Migration: 2017_12_31_063451_create_profiles_table
datebase/migrations/create_profiles_table.php(新規)
    public function up()
    {
        Schema::create('profiles', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned();
            $table->string('username');
            $table->biginteger('uid')->unsigned();
            $table->string('access_token');
            $table->string('access_token_secret');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('profiles');
    }

DBの作成。

$ php artisan migrate:reset
$ php artisan migrate

既存テーブルの構造を修正したので一度resetしています。

モデルの作成

モデルの場所は、デフォルトのままapp直下にしています。
微妙に宣言とか足りてなかったので参考資料に手を入れてます。

app/Profile.php(新規作成)
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Profile Extends Model
{

    public function user()
    {
        return $this->belongsTo('App\User');
    }
}
app/User.php
    public function profiles()
    {
        return $this->hasMany('App\Profile');
    }

ルーティングの設定

app.routes.phpとありますが……これはroutes/web.phpでいいのかな。
これに追記しました。

つないでみるが……ダメ……ッ!

指定されたアプリidは無効なアプリidのようです。とか言われてしまいました。
なんなん。
php-sdkがダメなんですかね。
そういえば以前利用した、socialiteとかいうやつならログインできています。
これ流用できたりするのかな?

今回のはroutes/web.phpに処理が記載されています。

Socialiteはapp/Http/Controllers/Auth/SocialController.phpというところで処理を記述していました。

ちょっと処理を見比べてみます。

ログイン部分

だいぶ処理の趣が異なってました。
が、やってることは変わらなくて、Socialiteを使えば1行でできるというくらいの差しかありませんでした。

よってスルー。

コールバック部分

どちらも戻り値的なところなのかfacebookのAPIなのかよくわかりませんが何らかの値を取得していました。

利用するパラメータは以下の通り。

  • 今回のやつ
    • user
      • uid
      • name(first_name + last_name)
      • email
      • username
    • profile
      • uid
      • username
      • access_token
      • access_token_secret
  • Socialiteのやつ
    • token
    • refreshToken
    • expiresIn
    • id
    • nickname
    • name
    • email
    • avatar
    • user
      • name
      • email
      • gender
      • verified
      • link
      • id
    • avatar_original
    • profileUrl

(ここでQiitaメンテが発生して泣いてました。Kobitoはこういうときに必要なのかもしれません)

修正案

方針としてはSocialController.phpのコールバック処理を書き換えることにします。

これに伴い、参照関係をいろいろと追加。
完成したのがこちら。

ここでこんなに処理書いちゃっていいのだろうかという一抹の不安がありますが無視します。

App/Http/Controllers/Auth/SocialController.php
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Socialite;
use DB;
use Auth;
use Redirect;
use App\User;
use App\Profile;

class SocialController extends Controller
{
    public function viewLogin()
    {
        return view('auth.login');
    }

    public function redirectToFacebookProvider()
    {
        return Socialite::driver('facebook')->redirect();
    }

    public function handleFacebookProviderCallback()
    {
        try{
            DB::transaction(function () {

                $me = Socialite::driver('facebook')->user();

                if($me){
                    $uid = $me->getId();

                    $profile = Profile::whereUid($uid)->first();


                    if (empty($profile)) {

                        $user = new User;
                        $user->name = $me->getName();
                        $user->email = $me->getEmail();
                        $user->photo = $me->getAvatar();
                        $user->password = "hogehoge";

                        $user->save();

                        $profile = new Profile();
                        $profile->uid = $uid;
                        $profile->username = $me->getName();
                        $profile->access_token = "fuga";
                        $profile->access_token_secret = "hoge";
                        $profile = $user->profiles()->save($profile);
                    }

                    $profile->access_token = "hoge";
                    $profile->access_token_secret = "fuga";
                    //$profile->access_token = $facebook->getAccessToken();
                    $profile->save();

                    $user = $profile->user;

                    Auth::login($user);

//                    dd($user);
                    dd($profile);
                }
            });

            return Redirect::to('/')->with('message', 'Facebookログインしました');

        }catch(Exception $e){
            return redirect("/");
        }
    }
}

アクセストークンとかなんか無視しちゃいけなさげなパラメータがちらほらと見えますが、とりあえず無視します。

できました(真顔)

試行錯誤部分

トランザクション

デバッグの最中に、usersだけに値が入ってprofilesに入っていない状態が発生しました。
profilesで存在確認を行うので、このままだとINSERTしようとしてしまい、キー重複でエラーになります。

正しく動けば発生しない状態ではあるものの、後のことも考えるとトランザクションの方法は調べておいて損はなさそうです。
というわけで、これを見ながらDB::transaction(function (){〜〜〜});を追加してます(反映済み)。

最初はsave()の前後だけでいいかと思ってたんですが、中が無名関数になるため変数的にいろいろ面倒になり、try全体を含めました。

リターンでリダイレクト返すの違う……?

なんかcallbackからページ遷移しませんでした。

と思ったら、リターンをトランザクションの中に入れてたのが動かない原因のようでした。
そりゃ動きませんて。

ついでにログインボタンを出したい

作ってるサービスの都合上、FBログインを必須にしたいので、本来のログインページを潰します。

というわけでルーティングをいじって、my.blade.phpあたりでメニューのログインを変更したり、ユーザー登録のメニューを消したりしました。
その部分がもともとhref="{{ route('login') }}"となっていたので、href="{{ url('auth/login/facebook') }}"に修正。

ログイン……させるときって、どんなボタンでしたっけ……?
そもそもポップアップで動くボタンがFB側からは配布されてますけど、これを使ったほうがいいんでしょうか。

あ、VALUのイメージでいいのか。
とりあえず今回はそんな感じで。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0