概要
Laravel5.5でTwitterログインが必要なサイトを作る過程でQiitaの情報を鵜呑みにしてたらハマりましたのでまとめることにしました。最終的にはYouTubeの動画で解決しましたのでそれをまとめたいと思います。
ちなみにLaravelのローカルサーバーで挙動を確認することはできませんので情報が全くありません。
(できるのかもしれないけどTwitterAPIでの登録URLでローカルサーバーのアドレスは受け付けてくれなかった)
Laravelのプロジェクトファイルをインストールする
$ composer create-project --prefer-dist laravel/laravel twitterlogin "5.5.*"
ユーザー認証の設定
$ php artisan make:auth
[結果]
Authentication scaffolding generated successfully.
mysqlのDBの作成
$ mysql -u root
mysql>
CREATE DATABASE `データベースの名前` DEFAULT CHARACTER SET utf8;
[結果]
Query OK, 1 row affected (0.00 sec)
マイグレーション
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=データベースの名前
DB_USERNAME=root
DB_PASSWORD=
$ php artisan migrate
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
解決方法はこちら
(参考)
Laravel5.5でphp artisan migrateした時にエラー「1071 Specified key was too long; max key length is 767 bytes」が発生
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema; // ← 追記
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Schema::defaultStringLength(191); // ← 追記
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}
これを設定した後に
$ php artisan migrate:fresh
[結果]
Dropped all tables successfully.
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table
を実行すれば良い
Socialiteのインポート
$ composer require laravel/socialite
'providers' => [
(省略)
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
Laravel\Socialite\SocialiteServiceProvider::class, // ← 追記
],
'aliases' => [
(省略)
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
'Socialite' => Laravel\Socialite\Facades\Socialite::class, // ← 追記
],
LoginControllerの実装
App\Http\Controllers\Auth\LoginController.php
においてSocialLoginの機能を実装します。
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Socialite; // <- 追記
use Auth; // <- 追記
use App\User; // <- 追記
class LoginController extends Controller
{
(省略)
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
// 追加
public function socialLogin($social)
{
return Socialite::driver($social)->redirect();
}
// 追加
public function handleProviderCallback($social)
{
$userSocial = Socialite::driver($social)->user();
$user = User::where(['email' => $userSocial->getEmail()])->first();
if ($user) {
Auth::login($user);
return redirect()->action('HomeController@index');
} else {
return view('auth.register', [
'name' => $userSocial->getName(),
'email' => $userSocial->getEmail()
]);
}
}
}
Routeの設定
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');
// 追加
Route::get('/login/{social}', 'Auth\LoginController@socialLogin')
->where('social', 'twitter|facebook|linkedin|google|github');
// 追加
Route::get('/login/{social}/callback', 'Auth\LoginController@handleProviderCallback')
->where('social', 'twitter|facebook|linkedin|google|github');
Twitterログインボタンの設置
login.blade.php
とregister.blade.php
にTwitterのログインボタンを設置します。
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Register</div>
<div class="panel-body">
<form class="form-horizontal" method="POST" action="{{ route('register') }}">
{{ csrf_field() }}
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
<label for="name" class="col-md-4 control-label">Name</label>
<div class="col-md-6">
@if(!empty($name))
<input id="name" type="text" class="form-control" name="name" value="{{ $name }}" required autofocus>
@else
<input id="name" type="text" class="form-control" name="name" value="{{ old('name') }}" required autofocus>
@endif
@if ($errors->has('name'))
<span class="help-block">
<strong>{{ $errors->first('name') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
<label for="email" class="col-md-4 control-label">E-Mail Address</label>
<div class="col-md-6">
@if(!empty($email))
<input id="email" type="email" class="form-control" name="email" value="{{ $email }}" required>
@else
<input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required>
@endif
@if ($errors->has('email'))
<span class="help-block">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
<label for="password" class="col-md-4 control-label">Password</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control" name="password" required>
@if ($errors->has('password'))
<span class="help-block">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group">
<label for="password-confirm" class="col-md-4 control-label">Confirm Password</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Register
</button>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">Or Register with</label>
<div class="row">
</div>
<div class="col-md-8 col-md-offset-2">
<a href="{{ url('login/twitter') }}" class="btn btn-social-icon btn-twitter"><i class="fa fa-twitter"></i> Twitter</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Login</div>
<div class="panel-body">
<form class="form-horizontal" method="POST" action="{{ route('login') }}">
{{ csrf_field() }}
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
<label for="email" class="col-md-4 control-label">E-Mail Address</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required autofocus>
@if ($errors->has('email'))
<span class="help-block">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
<label for="password" class="col-md-4 control-label">Password</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control" name="password" required>
@if ($errors->has('password'))
<span class="help-block">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<div class="checkbox">
<label>
<input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}> Remember Me
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-8 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Login
</button>
<a class="btn btn-link" href="{{ route('password.request') }}">
Forgot Your Password?
</a>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">Or login with</label>
<div class="row">
</div>
<div class="col-md-8 col-md-offset-2">
<a href="{{ url('login/twitter') }}" class="btn btn-social-icon btn-twitter"><i class="fa fa-twitter"></i> Twitter</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
twitterのAPIキーを実装する
config\service.php
にtwitterのクライアントidなどを設定します。
'sparkpost' => [
'secret' => env('SPARKPOST_SECRET'),
],
'stripe' => [
'model' => App\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
// 追加する
'twitter' => [
'client_id' => 'your client id ', // <- Consumer API keys (API keys)
'client_secret' => 'your client secret key', // <- Consumer API keys (API secret key)
'redirect' => 'twitter callback url'
],
これでやっとSocialiteでTwitterログインができるようになりました。
注意
今の時点でTwitterのAPIの設定でcallback url にlocalhost
のurlが設定できませんので開発環境でデバッグすることができませんでした。
つまり、http://127.0.0.1:8000
の指定ができませんでした。
ネットの情報ではhttp://127.0.0.1:8000
に指定できる前提が多かったですね。
そのため、わざわざテストのためにherokuにデプロイして確認していました。
callbackのurlをつどhttp://[herokuのアプリ名]/login/twitter/callback
という感じにTwitterのAPIのcallbackUrlを変更して開発していました。
例えば、herokuのアプリ名をtwittersample
とかにすると
http://twittersample.herokuapp.com
になるので
http://twittersample.herokuapp.com/login/twitter/callback
といった感じに設定します。
(参考)
[備忘録] Laravelをherokuにデプロイする(データベースはPostgreSQL) [メモ]
このcallbackurlが正しいのか判断できず何度もLaravelのプロジェクトファイルを削除したりherokuのアプリを削除したりハマっていました。
こんなしょうもない部分で他の人もハマって欲しくないので今回の記事を共有したいと思いました。
本当はハマらないのが一番いいです。