Как использовать оркестровые /tenanti в Laravel 5 для создания приложения с несколькими арендаторами с несколькими базами данных?

Я пытаюсь создать и использовать приложение с помощью Laravel 5. Предполагается, что это архитектура базы данных с несколькими арендаторами, использующая несколько баз данных. Мой работодатель требует этого для целей безопасности.

Я попытался вручную управлять основными переходами БД и миграциями Арендатора, но не смог. Поэтому я решил обратиться за помощью к конкретному пакету Laravel, который, предположительно, мне нужен.

Tenanti обеспечивает способ решения моей цели, но проблема в том, что я являюсь новичком-разработчиком, не могу полностью понять, как его использовать мое приложение.

Я правильно установил его, я полагаю, что делаю:

composer require "orchestra/tenanti=~3.0"

Добавление этих поставщиков и псевдонимов в файл конфигурационного приложения:

'providers' => [

    // ...
    Orchestra\Tenanti\TenantiServiceProvider::class,
    Orchestra\Tenanti\CommandServiceProvider::class,
],

'aliases' => [

    'Tenanti' => Orchestra\Support\Facades\Tenanti::class,

],

Наконец, опубликуем конфигурацию и настроим ее в соответствии с документацией для нескольких баз данных:

php artisan vendor:publish

return [
    'drivers' => [
        'user' => [
            'model'     => App\User::class,
            'migration' => 'tenant_migrations',
            'path'      => database_path('tenanti/user'),
        ],
    ],
];

В этот момент я все еще расплывчатый, что делать дальше?

Мои сомнения таковы:

  • Где будут созданы и сохранены файлы миграции? Я имею в виду, что в моем приложении есть два типа баз данных. Один набор файлов предназначен для основной БД, которая будет хранить всю информацию арендатора, а другие файлы будут для базы данных арендатора. Итак, как и где они будут храниться?
  • Я вижу слово "драйвер" в документации, но я не уверен, какой именно драйвер.
  • Как я буду обрабатывать аутентификацию для приложения? Я имею в виду, что каждый раз, когда приходит арендатор, мне нужно будет убедиться, что соединение с базой данных изменяется динамически. Как я это сделаю?
  • Я попытался пройти через хранилище самого пакета и понять код внутри, но напрасно. Я не очень хорош, когда речь идет о дизайне паттеров, таких как фасады, командная шина, поставщик услуг и т.д., Поэтому я не могу понять поток пакета или понять его.

Я попытался запустить некоторые из команд artisan, которые поставляются с пакетом, например:

php artisan tenanti:install {driver}
php artisan tenanti:make {driver} {name}

Но я получаю такую ​​ошибку:

[InvalidArgumentException] Соединение с базой данных [арендаторы] недоступны.

Где я могу найти ресурсы, чтобы понять, как это сделать?

Ответ 1

+1 для @морфофатического ответа, он очень точен на большинстве вещей.

Миграция

Один набор файлов предназначен для основного БД, который будет хранить всю информацию арендатора, а другие файлы будут для базы данных арендатора. Итак, как и где они будут храниться?

Для вашей основной базы данных вы сможете использовать по умолчанию database/migration и использовать php artisan make:migration и php artisan migrate.

Tenanti, однако, будет использовать путь миграции, установленный в конфигурации "драйвер". например:

'path' => database_path('tenanti/user'),

В этом случае миграция будет создана/перенесена из database/tenanti/user (вы можете выбрать другую папку, и она будет использовать эту папку). После этого вы можете создать новый файл миграции для арендатора-пользователя через php artisan tenanti:make user create_blogs_table (в качестве примера) и выполнить миграцию через php artisan tenanti:migrate user (см. Сходство между командой миграции Laravel и Tenanti?).

драйвера

Драйвер - это просто группировка арендатора, возможно, вы группируете его пользователями, компаниями или командой и т.д. И есть вероятность, что вам может потребоваться более одного типа группы для каждого проекта, иначе большую часть времени вы будете используя одиночную "группу" или "драйвер".

Аутентификация или доступ к БД

Как я буду обрабатывать аутентификацию для приложения? Я имею в виду, что каждый раз, когда приходит арендатор, мне нужно будет убедиться, что соединение с базой данных изменяется динамически. Как я это сделаю?

Прежде всего, вам нужно подумать о том, как вы планируете различать каждого арендатора. Большую часть времени я бы видел, как люди предпочитают выбирать субдомен. Поэтому в этом случае вам нужно проверить, принадлежит ли поддомен любому пользователю (путем запроса основной базы данных) с использованием промежуточного программного обеспечения, а затем подключиться к базе данных, которая принадлежит пользователю.

Tenanti не управляет этой частью процесса, потому что у каждого свой стиль по-разному, но мы предоставляем код для динамического подключения к вашему арендатору базы данных из базовой конфигурации базы данных.

Скажем, у вас есть следующая конфигурация:

<?php

return [
    'fetch' => PDO::FETCH_CLASS,
    'default' => 'primary',
    'connections' => [
        'primary' => [
            //
        ],
        'tenants' => [
                'driver'    => 'mysql',
                'host'      => 'dbhost',     // for user with id=1
                'username'  => 'dbusername', // for user with id=1
                'password'  => 'dbpassword', // for user with id=1
                'charset'   => 'utf8',
                'collation' => 'utf8_unicode_ci',
                'prefix'    => '',
                'strict'    => false,
            ],
       ],
    ],
    'migrations' => 'migrations',
    'redis' => [ ... ],
];

Вы можете выполнить шаг, доступный в https://github.com/orchestral/tenanti#multi-database-connection-setup и добавить следующий код.

<?php namespace App\Providers;

use Orchestra\Support\Facades\Tenanti;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Tenanti::setupMultiDatabase('tenants', function (User $entity, array $template) {
            $template['database'] = "tenant_{$entity->getKey()}";

            return $template;
        });
    }
}

Это обеспечит использование базы данных tenant_1 для базы данных user = 1, tenant_2 для пользователя = 2 и т.д.

Итак, как Tenanti обнаруживает, какой пользователь активен?

Здесь вам нужно добавить логику в ваше промежуточное ПО.

$user = App\User::whereSubdomain($request->route()->parameter('tenant'))->first();

Tenanti::driver('user')->asDefaultDatabase($user, 'tenants_{id}');

Ответ 2

Я никогда не использовал этот пакет, но, используя приведенный выше код, я думаю, что он, вероятно, близок к правильному решению. Вероятно, вам все равно придется играть с некоторыми из этих значений, чтобы получить их правильное:

Пути миграции

Поскольку вы используете конфигурацию с несколькими базами данных, я считаю, что вы должны сохранять миграцию в обычном месте, т.е. database/migrations. Tenanti затем создаст точную копию базы данных для каждого арендатора в другой базе данных. Однако при запуске php artisan tenanti:install user он может создать папку под database/, которая указывает, где вы должны поместить свои миграции.

Что такое "драйвер"?

driver описывает, будет ли Tenanti использовать одну или несколько баз данных, какие модели использовать для определения разных арендаторов и где хранить миграции. Это то, что вы указали в конфигурационном файле Tenanti, который вы использовали выше.

Выбор подключения к базе данных

Вам нужно обновить config/database.php следующим образом. В приложении normal Laravel у вас будет настройка соединения с DB следующим образом:

<?php
    return [
        'fetch' => PDO::FETCH_CLASS,
        'default' => env('DB_CONNECTION', 'mysql'),
        'connections' => [
            'sqlite' => [ ...DB connection info... ],
            'mysql'  => [ ...DB connection info... ],
            'pgsql'  => [ ...DB connection info... ],
            'sqlsrv' => [ ...DB connection info... ],
        ],
        'migrations' => 'migrations',
        'redis' => [ ... ],
    ];

Однако, в случае установки Tenanti multi-database, вам нужно добавить другую информацию о подключении для каждой базы данных арендатора. Для этого вы добавили новый уровень в ваш конфигурационный файл database.php (в этом примере предполагается, что вы используете mysql, но вы можете использовать любой БД или даже разные механизмы баз данных для разных арендаторов):

<?php
    return [
        'fetch' => PDO::FETCH_CLASS,
        'default' => env('DB_CONNECTION', 'mysql'),
        'connections' => [
            'tenants' => [
                'user_1' => [
                    'driver'    => 'mysql',
                    'host'      => 'dbhost',     // for user with id=1
                    'database'  => 'dbname',     // for user with id=1
                    'username'  => 'dbusername', // for user with id=1
                    'password'  => 'dbpassword', // for user with id=1
                    'charset'   => 'utf8',
                    'collation' => 'utf8_unicode_ci',
                    'prefix'    => '',
                    'strict'    => false,
                ],
                'user_2' => [
                    'driver'    => 'mysql',
                    'host'      => 'dbhost',     // for user with id=2
                    'database'  => 'dbname',     // for user with id=2
                    'username'  => 'dbusername', // for user with id=2
                    'password'  => 'dbpassword', // for user with id=2
                    'charset'   => 'utf8',
                    'collation' => 'utf8_unicode_ci',
                    'prefix'    => '',
                    'strict'    => false,
                ],
           ],
        ],
        'migrations' => 'migrations',
        'redis' => [ ... ],
    ];

Как вы можете видеть, каждый арендатор имеет свой собственный экземпляр базы данных, который может быть расположен на другом хосте и иметь другое имя пользователя/пароль. Tenanti нужно рассказать, как определить, какую базу данных использовать. Вот что описывает документация по подключению к базам данных. В своем примере они назвали свои базы данных арендаторов, используя acme_{$user->id}, тогда как в моем примере выше я использовал user_{$user->id}.

Как я уже сказал, я никогда не настраивал это самостоятельно, но это мои лучшие предположения, основанные на документах, и использование других пакетов этим же разработчиком. Надеюсь, это поможет!