99_27_hyn multi tenantによるマルチテナントアーキテクチャ - hpscript/laravel GitHub Wiki
$ composer create-project --prefer-dist laravel/laravel tenancy-demo
$ cd tenancy-demo
$ composer require hyn/multi-tenant
$ composer require "doctrine/dbal:2.*"
$ composer require tenancy/db-driver-mysql
config/app.php
'providers' => [
// 省略
Hyn\Tenancy\Providers\TenancyProvider::class,
Hyn\Tenancy\Providers\WebserverProvider::class,
],
file update
$ php artisan vendor:publish --tag tenancy
config/database.php
L connectionでmysqlをコピペしてsystemを追加します。
'connections' => [
'system' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'tenancy'),
'username' => env('DB_USERNAME', 'hoge'),
'password' => env('DB_PASSWORD', 'fuga'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
],
.env
TENANCY_HOST=127.0.0.1
TENANCY_PORT=3306
TENANCY_DATABASE=tenancy_demo
TENANCY_USERNAME=hoge
TENANCY_PASSWORD=fuga
mysql> create database tenancy_demo;
Query OK, 1 row affected (0.01 sec)
$ php artisan migrate --database=system
Migrating: 2017_01_01_000003_tenancy_websites
Migrated: 2017_01_01_000003_tenancy_websites (16.88ms)
Migrating: 2017_01_01_000005_tenancy_hostnames
Migrated: 2017_01_01_000005_tenancy_hostnames (44.02ms)
Migrating: 2018_04_06_000001_tenancy_websites_needs_db_host
Migrated: 2018_04_06_000001_tenancy_websites_needs_db_host (12.21ms)
multi tenantのテストを行うには、apacheかlaravel Valetでテストする必要がある
$ sudo vi /etc/httpd/conf.d/custom.conf
DocumentRoot "/var/www/html/tenancy-demo/public"
# .htaccess 有効化
<Directory /var/www/html/tenancy-demo/public>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
Require all granted
</Directory>
$ service httpd restart
routes/tenants.php
use Illuminate\Support\Facades\Route;
Route::get('/', function(){
return view('tenants.home');
});
resources/views/tenants/home.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Welcom!</h1>
<p>This will be your <b>dashboard</b> for every tenant in your system.</p>
</body>
</html>
config/tenancy.php
L make sure that path would be right.
'routes' => [
'path' => base_path('routes/tenants.php'),
'replace-global' => false,
],
$ php artisan make:command tenant/create
app/Console/Commands/tenant/create.php
namespace App\Console\Commands\tenant;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use Hyn\Tenancy\Models\Hostname;
use Hyn\Tenancy\Models\Website;
use Hyn\Tenancy\Repositories\HostnameRepository;
use Hyn\Tenancy\Repositories\WebsiteRepository;
class create extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
// protected $signature = 'command:name';
protected $signature = 'tenant:create {fqdn}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Given a unique tenant name, creates a new tenant in the sytem';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$fqdn = sprintf('$s.$s', $this->argument('fqdn'), env('APP_DOMAIN'));
$website = new Website;
$website->uuid = env('TENANT_WEBSITE_PREFIX') . Str::random(6);
app(WebsiteRepository::class)->create($website);
$hostname = new Hostname;
$hostname->fqdn = $fqdn;
$hostname = app(HostnameRepository::class)->create($hostname);
app(HostnameRepository::class)->attach($hostname, $website);
// return 0;
}
}
.env
TENANT_WEBSITE_PREFIX=tenancy_demo_
php artisan tenant:create demo
mysql> show tables;
+------------------------+
| Tables_in_tenancy_demo |
+------------------------+
| failed_jobs |
| hostnames |
| migrations |
| password_resets |
| users |
| websites |
+------------------------+
6 rows in set (0.31 sec)
mysql> select * from websites;