はじめに (対象読者・この記事でわかること)

この記事はLaravelを使用したWeb開発を経験している方を対象にしています。特にGoogle APIを利用したソーシャルログイン機能を実装しようとしている方や、既に実装した際にプロフィール画像の表示で困っている方に役立つ内容です。

この記事を読むことで、Laravel8.xでGoogle APIによるログイン機能を実装し、ユーザーのプロフィール画像をセッションに保存した際にBladeテンプレートで正しく表示させるための具体的な解決策がわかります。実装中に遭遇する画像が表示されない問題の原因と、それを解決するためのコード例を詳しく解説します。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 前提となる知識1 (例: PHPとLaravelの基本的な知識) 前提となる知識2 (例: Google Cloud ConsoleでAPI認証情報を取得する方法)

Google APIログイン機能の実装とプロフィール画像表示の問題点

Webアプリケーション開発において、ユーザー認証は必須の機能です。特に最近では、Googleアカウントなどを利用したソーシャルログインが一般的になっています。Laravelフレームワークでは、Laravel Socialiteパッケージを使用することで簡単にGoogle OAuthを実装できます。

しかし、実際に実装を進める中で、プロフィール画像をセッションに保存した際にBladeテンプレート上で正しく表示されないという問題に多くの開発者が直面します。この問題の原因は、セッションに保存する画像データの形式や、Bladeで画像を表示する際の記述方法に起因することが多いです。

この記事では、Laravel8.x環境でGoogle APIによるログインを実装し、ユーザーのプロフィール画像をセッションに保存してBladeで表示させるまでの流れを解説。特に画像が表示されない問題の原因と、その解決策に焦点を当てて詳しく説明します。

具体的な実装手順とプロフィール画像の表示方法

ステップ1:必要なパッケージのインストールと設定

まず、Laravelプロジェクトに必要なパッケージをインストールします。ターミナルで以下のコマンドを実行してください:

Bash
composer require laravel/socialite

次に、config/services.php ファイルを編集してGoogle APIの設定を追加します:

Php
'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => 'http://your-app-url.com/auth/google/callback', ],

.env ファイルにはGoogle Cloud Consoleで取得したクライアントIDとクライアントシークレットを設定します:

GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

ステップ2:認証機能の実装

まず、Googleログイン用のコントローラーを作成します:

Bash
php artisan make:controller Auth/GoogleController

作成したコントローラーに以下のコードを記述します:

Php
<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Socialite; use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Session; class GoogleController extends Controller { /** * Googleへのリダイレクト */ public function redirectToGoogle() { return Socialite::driver('google')->redirect(); } /** * Googleからのコールバック処理 */ public function handleGoogleCallback() { try { $user = Socialite::driver('google')->user(); // ユーザーが存在するか確認 $finduser = User::where('google_id', $user->id)->first(); if($finduser){ // ユーザーが存在する場合、ログイン Auth::login($finduser); return redirect()->intended('dashboard'); }else{ // ユーザーが存在しない場合、新規作成 $newUser = User::create([ 'name' => $user->name, 'email' => $user->email, 'google_id'=> $user->id, 'password' => encrypt('123456dummy') ]); // プロフィール画像をセッションに保存 Session::put('profile_image', $user->avatar); Auth::login($newUser); return redirect()->intended('dashboard'); } } catch (Exception $e) { return redirect('auth/google'); } } }

ルートファイルに以下のルートを追加します:

Php
Route::get('auth/google', [GoogleController::class, 'redirectToGoogle']); Route::get('auth/google/callback', [GoogleController::class, 'handleGoogleCallback']);

ステップ3:プロフィール画像の表示と問題点

ここが問題の核心部分です。まず、セッションに保存したプロフィール画像をBladeで表示しようとすると、多くの開発者が以下のようなコードを書きます:

Html
<img src="{{ Session::get('profile_image') }}" alt="プロフィール画像">

しかし、この方法では画像が正しく表示されないことがあります。その原因と解決策を以下に説明します。

ハマった点やエラー解決

問題1:画像が表示されない

多くの場合、Google APIから取得するプロフィール画像URLは一時的なものであり、直接参照しても表示されない場合があります。また、セッションに保存したURLをそのままBladeで使用すると、URLの形式が正しくないために画像が表示されないことがあります。

問題2:セッションデータが保持されない

ページをリロードすると、セッションに保存したプロフィール画像データが失われることがあります。これはセッションの設定やLaravelのキャッシュ設定に関連している可能性があります。

解決策

解決策1:画像データをBase64形式で保存する

Google APIから取得した画像データをBase64形式に変換してセッションに保存する方法です。これにより、画像のURLではなく画像そのものを保存できるため、表示の安定性が向上します。

まず、GoogleControllerのhandleGoogleCallbackメソッドを修正します:

Php
// プロフィール画像をBase64形式で取得・保存 $imageContent = file_get_contents($user->avatar); $imageBase64 = base64_encode($imageContent); $imageType = pathinfo($user->avatar, PATHINFO_EXTENSION); $imageData = 'data:image/' . $imageType . ';base64,' . $imageBase64; Session::put('profile_image_base64', $imageData);

次に、Bladeテンプレートで以下のように表示します:

Html
<img src="{{ Session::get('profile_image_base64') }}" alt="プロフィール画像">

解決策2:画像を保存してパスをセッションに保存する

もう一つの方法は、画像をサーバーに保存してそのパスをセッションに保存する方法です。この方法では、画像の表示が高速になります。

まず、storage/app/publicディレクトリに画像を保存するためのディレクトリを作成します:

Bash
mkdir -p storage/app/public/profile_images

GoogleControllerのhandleGoogleCallbackメソッドを以下のように修正します:

Php
use Illuminate\Support\Facades\Storage; // プロフィール画像を保存 $imageContent = file_get_contents($user->avatar); $imageName = 'profile_' . $user->id . '.jpg'; Storage::disk('public')->put('profile_images/' . $imageName, $imageContent); // 画像のパスをセッションに保存 Session::put('profile_image_path', 'storage/profile_images/' . $imageName);

Bladeテンプレートで以下のように表示します:

Html
<img src="{{ asset(Session::get('profile_image_path')) }}" alt="プロフィール画像">

解決策3:ミドルウェアを使用したセッションの永続化

セッションデータが保持されない問題を解決するために、ミドルウェアを使用してセッションを適切に管理します。

まず、ミドルウェアを作成します:

Bash
php artisan make:middleware EnsureSessionData

作成したミドルウェアを以下のように編集します:

Php
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Session; class EnsureSessionData { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { $response = $next($request); // ユーザーがログインしている場合、セッションデータを更新 if (Auth::check()) { $user = Auth::user(); // プロフィール画像のパスをセッションに保存 if ($user->profile_image_path) { Session::put('profile_image_path', $user->profile_image_path); } } return $response; } }

app/Http/Kernel.php ファイルにミドルウェアを登録します:

Php
protected $middlewareGroups = [ 'web' => [ // 他のミドルウェア... \App\Http\Middleware\EnsureSessionData::class, ], ];

さらに、ユーザーモデルにプロフィール画像のパスを保存するためのカラムを追加します:

Bash
php artisan make:migration add_profile_image_path_to_users_table --table=users

マイグレーションファイルを以下のように編集します:

Php
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class AddProfileImagePathToUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('users', function (Blueprint $table) { $table->string('profile_image_path')->nullable()->after('google_id'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('profile_image_path'); }); } }

マイグレーションを実行します:

Bash
php artisan migrate

GoogleControllerのhandleGoogleCallbackメソッドを修正して、ユーザーモデルに画像のパスを保存します:

Php
// プロフィール画像を保存 $imageContent = file_get_contents($user->avatar); $imageName = 'profile_' . $user->id . '.jpg'; $imagePath = 'profile_images/' . $imageName; Storage::disk('public')->put($imagePath, $imageContent); // ユーザーモデルに画像のパスを保存 $newUser->profile_image_path = 'storage/' . $imagePath; $newUser->save();

これにより、ユーザーモデルにプロフィール画像のパスが保存され、セッションにも保存されるため、ページをリロードしても画像が表示され続けます。

まとめ

本記事では、Laravel8.xでGoogle APIによるログイン機能を実装した際に、プロフィール画像をセッションに保存してBladeで表示させる方法について解説しました。

  • プロフィール画像の表示問題の原因は、Google APIから取得する画像URLの一時的な性質や、セッションに保存したデータの形式に起因することが多い
  • 解決策として、Base64形式で画像データを保存する方法や、画像をサーバーに保存してパスをセッションに保存する方法がある
  • セッションデータの永続化には、ミドルウェアを使用してセッションを適切に管理する方法が有効

この記事で紹介した方法を実装することで、ユーザーのプロフィール画像を安定して表示させることができます。今後は、画像のリサイズや最適化に関する機能の実装についても記事にする予定です。

参考資料