【发布时间】:2021-09-22 08:14:35
【问题描述】:
我有一点鸡和蛋的问题。我正在 Laravel 中构建一个多租户应用程序,每个租户在 Postgrsql 服务器上都有自己的数据库。所以我有一个工作来创建一个新租户,它调用:
Schema::connection($this->tenant->getDatabaseConnection())->createDatabase($this->tenant->getDatabaseName())
所以$this->tenant->getDatabaseConnection() 选择一个租户数据库服务器来添加租户并返回那个服务器的连接名称。然后$this->tenant->getDatabaseName() 将返回该租户的数据库名称字符串。
我遇到了一个小问题。这会引发异常:
SQLSTATE[08006] [7] 致命:数据库“port=5432”不存在(SQL: 创建数据库“local_tenant_(id)”编码“utf8”)
这是因为默认情况下连接的数据库名称为空。当用户登录到他们的租户时,我们会动态地将租户模型中的 getDatabaseName() 注入其中。
但我不能在这里这样做,因为租户数据库还不存在。所以这里是我看到的选项:
-
在创建新租户的数据库时,选择服务器上现有租户的随机数据库来“充当”。我真的不喜欢像这样暂时劫持另一个租户的数据库,即使这对那个租户应该有 0 的副作用。如果它是在服务器上配置的第一个租户,则没有可使用的现有数据库,这使得这在我自己的书中是不可行的。
-
我可以只使用数据库提供者 API 来创建租户数据库。这将是迄今为止最简单的,但会在本地和测试环境中中断,因此我想避免。
-
我可以绕过 Laravel 并为此建立与数据库的直接 PDO 连接,但如果我找不到更好的东西,我会说这是我最后的手段。
从技术上讲,您不必选择一个数据库来使用创建数据库命令。这是 Laravel 的 Schema Builder 的一个特性,它会在调用方法之前尝试选择一个 DB(在本例中为 CreatedDatabase)。有没有办法解决这个问题,所以我可以在 Laravel 不首先尝试选择空数据库的情况下创建数据库?
【问题讨论】:
-
您可以这样做,但我想知道为什么,以及您的迁移策略是什么,假设您有 1000 个租户,您将如何向特定的每个数据库中的表? (我问这个问题是因为我想知道你是否考虑过这个问题。如果是这样,我对你的策略很感兴趣)
-
@Tropus 每租户数据库策略是最具可扩展性的多租户选项。请参阅 Tom Schlick 的 this Laracon talk 了解多租户策略。我正在使用spatie/laravel-multitenancy 包。它处理核心逻辑以使租户对给定请求“活跃”。它动态调整租户连接中的“DB_NAME”。任何特定于租户的模型都使用该连接。但是我仍然需要使用这个包手动处理配置/取消配置租户。
-
@Tropus 至于迁移,该软件包包括一种以特定租户身份运行任何工匠命令(例如“迁移”)的方法,或者您可以传入租户 ID 列表,它将循环遍历所有他们。我将运行 migrate 命令的多个实例,每个实例都有一个不同的要迁移的tenant_id 列表。这加上提前计划迁移应该可以正常工作。
标签: php laravel postgresql laravel-8 laravel-schema-builder