mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-05 06:54:05 +00:00
wip
This commit is contained in:
parent
2ff3dd4283
commit
743369cde7
6 changed files with 107 additions and 32 deletions
|
|
@ -59,8 +59,8 @@ return [
|
|||
// Tenant database managers handle the creation & deletion of tenant databases.
|
||||
'sqlite' => Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager::class,
|
||||
'mysql' => Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager::class,
|
||||
'pgsql' => Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager::class,
|
||||
'schema' => Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager::class
|
||||
// 'pgsql' => Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager::class,
|
||||
'pgsql' => Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLSchemaManager::class, // Separate by schema instead of database
|
||||
],
|
||||
'database_manager_connections' => [
|
||||
// Connections used by TenantDatabaseManagers. This tells, for example, the
|
||||
|
|
@ -68,9 +68,8 @@ return [
|
|||
'sqlite' => 'sqlite',
|
||||
'mysql' => 'mysql',
|
||||
'pgsql' => 'pgsql',
|
||||
'schema' => 'pgsql'
|
||||
],
|
||||
'using_schema_connection' => false, // Only work with pgsql connection
|
||||
'separate_by' => 'database', // database or schema (only supported by pgsql)
|
||||
'bootstrappers' => [
|
||||
// Tenancy bootstrappers are executed when tenancy is initialized.
|
||||
// Their responsibility is making Laravel features tenant-aware.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace Stancl\Tenancy;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Database\DatabaseManager as BaseDatabaseManager;
|
||||
use Illuminate\Foundation\Application;
|
||||
|
|
@ -100,12 +101,9 @@ class DatabaseManager
|
|||
|
||||
// Change database name.
|
||||
$databaseName = $this->getDriver($connectionName) === 'sqlite' ? database_path($databaseName) : $databaseName;
|
||||
$separateBy = $this->separateBy($connectionName);
|
||||
|
||||
if ($this->isUsingSchema($connectionName)) {
|
||||
$this->app['config']["database.connections.$connectionName.schema"] = $databaseName;
|
||||
} else {
|
||||
$this->app['config']["database.connections.$connectionName.database"] = $databaseName;
|
||||
}
|
||||
$this->app['config']["database.connections.$connectionName.$separateBy"] = $databaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -231,7 +229,7 @@ class DatabaseManager
|
|||
*/
|
||||
public function getTenantDatabaseManager(Tenant $tenant): TenantDatabaseManager
|
||||
{
|
||||
$driver = $this->isUsingSchema($tenant->getConnectionName()) ? 'schema' : $this->getDriver($this->getBaseConnection($tenant->getConnectionName()));
|
||||
$driver = $this->getDriver($this->getBaseConnection($tenant->getConnectionName()));
|
||||
|
||||
$databaseManagers = $this->app['config']['tenancy.database_managers'];
|
||||
|
||||
|
|
@ -243,13 +241,18 @@ class DatabaseManager
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if using schema connection
|
||||
* What key on the connection config should be used to separate tenants.
|
||||
*
|
||||
* @param string $connectionName
|
||||
* @return bool
|
||||
* @return string
|
||||
*/
|
||||
protected function isUsingSchema(string $connectionName): bool
|
||||
public function separateBy(string $connectionName): string
|
||||
{
|
||||
return $this->getDriver($this->getBaseConnection($connectionName)) === 'pgsql' && $this->app['config']['tenancy.using_schema_connection'];
|
||||
if ($this->getDriver($this->getBaseConnection($connectionName)) === 'pgsql'
|
||||
&& $this->app['config']['tenancy.separate_by'] === 'schema') {
|
||||
return 'schema';
|
||||
}
|
||||
|
||||
return 'database';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class PostgreSQLSchemaManager implements TenantDatabaseManager
|
|||
|
||||
public function __construct(Repository $config, IlluminateDatabaseManager $databaseManager)
|
||||
{
|
||||
$this->database = $databaseManager->connection($config['tenancy.database_manager_connections.schema']);
|
||||
$this->database = $databaseManager->connection($config['tenancy.database_manager_connections.pgsql']);
|
||||
}
|
||||
|
||||
public function createDatabase(string $name): bool
|
||||
|
|
|
|||
|
|
@ -4,26 +4,24 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Tests;
|
||||
|
||||
use Stancl\Tenancy\DatabaseManager;
|
||||
use Stancl\Tenancy\Tenant;
|
||||
|
||||
class DatabaseSchemaManagerTest extends TestCase
|
||||
{
|
||||
public $autoInitTenancy = false;
|
||||
|
||||
/**
|
||||
* Define environment setup.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
* @return void
|
||||
*/
|
||||
protected function getEnvironmentSetUp($app)
|
||||
{
|
||||
parent::getEnvironmentSetUp($app);
|
||||
|
||||
$app['config']->set('database.default', 'pgsql');
|
||||
$app['config']->set('tenancy.database.based_on', null);
|
||||
$app['config']->set('tenancy.database.suffix', '');
|
||||
$app['config']->set('tenancy.using_schema_connection', true);
|
||||
$app['config']->set([
|
||||
'database.default' => 'pgsql',
|
||||
'database.connections.pgsql.database' => 'main',
|
||||
'database.connections.pgsql.schema' => 'public',
|
||||
'tenancy.database.based_on' => null,
|
||||
'tenancy.database.suffix' => '',
|
||||
'tenancy.separate_by' => 'schema',
|
||||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
|
@ -37,8 +35,7 @@ class DatabaseSchemaManagerTest extends TestCase
|
|||
|
||||
$new_connection_name = app(\Illuminate\Database\DatabaseManager::class)->connection()->getName();
|
||||
|
||||
// $this->assertSame($old_connection_name, $new_connection_name);
|
||||
$this->assertNotEquals('tenant', $new_connection_name);
|
||||
$this->assertSame($old_connection_name, $new_connection_name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
|
@ -66,4 +63,79 @@ class DatabaseSchemaManagerTest extends TestCase
|
|||
|
||||
$this->assertSame($tenant->getDatabaseName(), config('database.connections.' . config('database.default') . '.schema'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function databases_are_separated_using_schema_and_not_database()
|
||||
{
|
||||
tenancy()->create('foo.localhost');
|
||||
tenancy()->init('foo.localhost');
|
||||
$this->assertSame('tenant', config('database.default'));
|
||||
$this->assertSame('main', config('database.connections.tenant.database'));
|
||||
|
||||
$schema1 = config('database.connections.' . config('database.default') . '.schema');
|
||||
$database1 = config('database.connections.' . config('database.default') . '.database');
|
||||
|
||||
tenancy()->create('bar.localhost');
|
||||
tenancy()->init('bar.localhost');
|
||||
$this->assertSame('tenant', config('database.default'));
|
||||
$this->assertSame('main', config('database.connections.tenant.database'));
|
||||
|
||||
$schema2 = config('database.connections.' . config('database.default') . '.schema');
|
||||
$database2 = config('database.connections.' . config('database.default') . '.database');
|
||||
|
||||
$this->assertSame($database1, $database2);
|
||||
$this->assertNotSame($schema1, $schema2);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function databases_are_separated()
|
||||
{
|
||||
// copied from DataSeparationTest
|
||||
|
||||
$tenant1 = Tenant::create('tenant1.localhost');
|
||||
$tenant2 = Tenant::create('tenant2.localhost');
|
||||
\Artisan::call('tenants:migrate', [
|
||||
'--tenants' => [$tenant1['id'], $tenant2['id']],
|
||||
]);
|
||||
|
||||
tenancy()->init('tenant1.localhost');
|
||||
User::create([
|
||||
'name' => 'foo',
|
||||
'email' => 'foo@bar.com',
|
||||
'email_verified_at' => now(),
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
'remember_token' => Str::random(10),
|
||||
]);
|
||||
$this->assertSame('foo', User::first()->name);
|
||||
|
||||
tenancy()->init('tenant2.localhost');
|
||||
$this->assertSame(null, User::first());
|
||||
|
||||
User::create([
|
||||
'name' => 'xyz',
|
||||
'email' => 'xyz@bar.com',
|
||||
'email_verified_at' => now(),
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
'remember_token' => Str::random(10),
|
||||
]);
|
||||
|
||||
$this->assertSame('xyz', User::first()->name);
|
||||
$this->assertSame('xyz@bar.com', User::first()->email);
|
||||
|
||||
tenancy()->init('tenant1.localhost');
|
||||
$this->assertSame('foo', User::first()->name);
|
||||
$this->assertSame('foo@bar.com', User::first()->email);
|
||||
|
||||
$tenant3 = Tenant::create('tenant3.localhost');
|
||||
\Artisan::call('tenants:migrate', [
|
||||
'--tenants' => [$tenant1['id'], $tenant3['id']],
|
||||
]);
|
||||
|
||||
tenancy()->init('tenant3.localhost');
|
||||
$this->assertSame(null, User::first());
|
||||
|
||||
tenancy()->init('tenant1.localhost');
|
||||
DB::table('users')->where('id', 1)->update(['name' => 'xxx']);
|
||||
$this->assertSame('xxx', User::first()->name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class TenantDatabaseManagerTest extends TestCase
|
|||
['mysql', MySQLDatabaseManager::class],
|
||||
['sqlite', SQLiteDatabaseManager::class],
|
||||
['pgsql', PostgreSQLDatabaseManager::class],
|
||||
['schema', PostgreSQLSchemaManager::class]
|
||||
['pgsql', PostgreSQLSchemaManager::class]
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,12 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
|||
Redis::connection('tenancy')->flushdb();
|
||||
Redis::connection('cache')->flushdb();
|
||||
|
||||
$originalConnection = config('database.default');
|
||||
$this->loadMigrationsFrom([
|
||||
'--path' => realpath(__DIR__ . '/../assets/migrations'),
|
||||
'--database' => 'central',
|
||||
]);
|
||||
config(['database.default' => 'sqlite']); // fix issue caused by loadMigrationsFrom
|
||||
config(['database.default' => $originalConnection]); // fix issue caused by loadMigrationsFrom
|
||||
|
||||
if ($this->autoCreateTenant) {
|
||||
$this->createTenant();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue