Я пытаюсь создать мультитенантное приложение с Laravel 5. Мне известны уже существующие пакеты, такие как Hyn и AuraEQ, но я все еще нахожу их сложными для понимания, и я хочу сделать свою собственную (упрощенную) версию. Таким образом, я точно знаю, что происходит под капотом. Я прочитал почти все в Интернете, прежде чем начать, но по этому вопросу не так много информации.
Подход, который я имею в виду, довольно прост:
app/config/tenant.php
и базовое соединение с базой данных в app/config/database.php
, Я думаю, что хранить арендаторов в «основной» базе данных — это излишне.getConnectionName()
выполнять запросы в активной базе данных арендаторовКаждый веб-сайт (арендатор) имеет свою собственную папку в пути хранения. Допустим, у меня есть веб-сайт с именем «coding.com», путь будет примерно таким: app/storage/tenants/coding-com
, Арендатор в настоящее время имеет свои собственные взгляды и маршруты.
Пока все хорошо, это код:
class TenantServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->app->singleton('Tenant', function () {
$tenants = config('tenant.hosts');
$host = Request::server('HTTP_HOST');
if(array_key_exists($host, $tenants)) {
return $tenants[$host];
}
return null;
});
$tenant = $this->app->make('Tenant');
$directory = tenant_path($tenant);
if($tenant && is_dir($directory)) {
// Load views from the current tenant directory
$this->app['view']->addLocation($directory . '/views');
// Load optional routes from the current tenant directory
if(file_exists($directory . '/routes.php')) require_once $directory . '/routes.php';
}
// Load base views, these will be overridden by tenant views with the same name
$this->app['view']->addLocation(realpath(base_path('resources/views')));
}
}
Определение палаток:
return [
/**
* Base path of the tenant's directory.
*/
'path' => storage_path('tenants'),
/**
* This is where the tenants are defined.
*/
'hosts' => [
'coding.com' => [
'id' => 'coding-com', // Connection within config/database.php is also named coding-com
'https' => false,
],
'other.com' => [
'id' => 'other-nl',
'https' => false,
]
]
];
И я должен расширить каждую модель Eloquent классом TentantModel, который переопределяет getConnectionName()
метод:
/**
* Get the current connection name for the model.
*
* @return string
*/
public function getConnectionName()
{
$tenant = app()->make('Tenant');
if($tenant) {
return array_get($tenant, 'id');
}
return parent::getConnectionName();
}
Я извиняюсь за большие куски кода, но это делает идею намного проще для понимания.
Это подводит меня к нескольким вопросам:
Ответ на один был бы очень признателен. Заранее спасибо!
Задача ещё не решена.
Других решений пока нет …