我可以在不先选择数据库的情况下使用 Laravel Schema::create Database() 吗?

Posted

技术标签:

【中文标题】我可以在不先选择数据库的情况下使用 Laravel Schema::create Database() 吗?【英文标题】:Can I use Laravel's Schema::createDatabase() without first selecting a DB? 【发布时间】: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 列表。这加上提前计划迁移应该可以正常工作。 【参考方案1】:

正确的解决方案是连接到postgres 数据库以运行CREATE DATABASEpostgres 数据库始终存在(除非有人丢弃它),这就是它的设计目的。

【讨论】:

来自 mysql 我什至没有意识到那只是一个空数据库。我以为这相当于“mysql”数据库,不想碰它。谢谢你的提示。奇迹般有效。我的一部分不喜欢必须选择一个我没有真正使用的数据库,但由于它只是一个空的默认值,所以它不是一个可怕的选项。

以上是关于我可以在不先选择数据库的情况下使用 Laravel Schema::create Database() 吗?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在不先列出列表的情况下将 Series 附加到 DataFrame 行?

如何在不先定义表中的列的情况下将数据加载到 PostgreSQL 中?

在不先显示 UIView 的情况下将 UIView 转换为 UIImage?

在 PHP 中是不是可以在不先提取其内容的情况下检查 Zip 文件的内容?

如何在不先加载到 RAM 的情况下将文件加载到 blob 中?

如何在不先保存的情况下在 Android 中发送 zip 文件?