Laravelの利点にDBの扱いやすさがありますよね、これまでDB周りで詰まったことはほとんどありませんでしたが、DBを動的に変更する機能で詰まったので、備忘録として残しておきます。
使用環境
・MAC
・Laravel7.5
・Tenancy ←本記事の主役
作りたかったもの
Laravelで※シングルサインオン(SSO)機能のAPI認証基盤の構築。
DBはユーザーが新規で登録されるごとに新規で構築され、ログイン中のユーザーごとに切り替える。
※Single Sign Onの略。1つのIDとパスワードを入力して、複数のWebサービスやアプリケーションにログインする仕組み。
詰まった箇所
・ユーザーが新規登録される毎にDBをプログラム内で(自動で)構築する
・DBが構築される毎に構築されたDBにテーブルを作成する(マイグレーションを実行する)
・ログイン中のユーザーごとにDBを切り替える
詰まった原因
LaravelでDBを扱うにはconfig/database.phpにDB情報を、前もって記入しておく必要があります。
(PDOでDBに直接接続するなど別方法もありますが、ここでは割愛させてください。)
しかし、今回作りたかった機能としてDBを動的に切り替える必要があるのですが、config/database.phpに前もって記入することができなかったからです。
解決策
####・Tenancyを使用し、マルチテナント環境を構築する。
https://reffect.co.jp/laravel/laravel-multi-tenant-stancl-tenancy
Tenancyの使用方法については👆に記載されています。
👇のコードでテナント(ユーザーごとの環境)・テナントごとのDBとテーブルの構築までします。
//ユーザー登録機能内にテナント作成機能を追加(一部抜粋)
//リクエストされたユーザー名
$user_name = $request['user_name'];
//メインドメイン
$baseURL = 'qiita.com';
//ユーザー名でテナントを作成
$tenant = Tenant::new()->withDomains($user_name . '.' . $baseURL)->save();
//migrate実行(実行したいマイグレーションファイルは/database/migrations/tenantに格納しておく)
$exit = \Artisan::call('tenants:migrate', ['--force' => true,]);
これで以後は、「リクエストされたユーザー名.メインドメイン」のURLにアクセスすると、
そのユーザー用のページにアクセスすることができ、ユーザーに対応したDBに自動で切り替えられます。
(ここら辺の動きを詳しく知りたい方は👇をどうぞ)
https://tenancy.dev/
実際にはこんな感じでテナント用ページにアクセスし、API認証機能を実装しました。
$tenant_name = 'foo.';
$baseURL = $tenant_name . 'qiita.com/';
$client = new \GuzzleHttp\Client(['base_uri' => 'http://'. $baseURL]);
$response = $client->request(
'POST',
'changeProfile',
[
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$api_token
],
'form_params' => [
'profile' => $profile,
'email' => $email,
],
]
);