LoginSignup
0
0

マルチログインでモデルを変更したけどsessionテーブルも変更したい

Posted at

背景

マルチログインで、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以来触ってなかったけど、洗練されて来ている感

他にいい方法あるのかな?

0
0
1

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
0
0