背景
マルチログインで、databaseにそれぞれセッション持たせたかった。
前提
Laravel 11
テーブル例:users、sessions、admins、admin_sessions
config/auth.auth
にはguard
として、user
admin
を追加済み
結論
セッションテーブルの切り替え
認証ユーザー属性によって、参照するテーブルを切り替える。
ミドルウェアの作成
サンプルコード
CustomSessionTable.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Symfony\Component\HttpFoundation\Response;
class CustomSessionTable
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
// ガードに応じてセッションテーブルを変更する
if (Auth::guard('admin')->check()) {
Config::set('session.table', 'admin_sessions');
} else {
Config::set('session.table', 'sessions');
}
return $next($request);
}
}
ミドルウェアの登録
Laravel 11 からは bootstrap/app.php
に登録する
サンプルコード
app.php
.
.
.
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
api: __DIR__.'/../routes/api.php',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->append(
\App\Http\Middleware\CustomSessionTable::class
);
})
->withExceptions(function (Exceptions $exceptions) {
})->create();
.
.
.
sessionテーブルの参照カラムをデフォルト(user_id)から変更
sessionsテーブル書き込み時には、user_id カラムに紐づくusersテーブルのidが格納される。
admin_sessions を参照していても同様に、user_idを参照する。
admin_sessions テーブルの中に、多分user_id定義すれば済む話だけど
なんか気持悪いので、参照カラムを切り替える。
カスタムセッションハンドラ の追加
path はお好きに。
例は App\Extensions
サンプルコード
DatabaseSessionHandler.php
<?php
namespace App\Extensions;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Session\DatabaseSessionHandler as BaseDatabaseSessionHandler;
use SessionHandlerInterface;
class DatabaseSessionHandler extends BaseDatabaseSessionHandler implements SessionHandlerInterface
{
protected function addUserInformation(&$payload)
{
if ($this->container->bound(Guard::class)) {
if(config('session.table') === 'admin_sessions') {
$payload['admin_id'] = $this->container->make(Guard::class)->id();
} else {
$payload['user_id'] = $this->container->make(Guard::class)->id();
}
}
return $this;
}
}
カスタムプロバイダ の追加
AppServiceProviderに直接入れてもいいけど
分離したい
サンプルコード
CustomSessionServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Extensions\DatabaseSessionHandler;
class CustomSessionServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->app->resolving('session', function ($session) {
$session->extend('database', function ($app) {
$connection = $app->make('db')->connection();
$table = config('session.table');
$minutes = config('session.lifetime');
return new DatabaseSessionHandler($connection, $table, $minutes);
});
});
}
}
プロバイダの登録
Laravel 11 からは bootstrap/providers.php
に登録する
サンプルコード
providers.php
<?php
return [
App\Providers\AppServiceProvider::class,
App\Providers\CustomSessionServiceProvider::class,
];
〆
Laravelは8以来触ってなかったけど、洗練されて来ている感
他にいい方法あるのかな?