【问题标题】:Can't install Laravel to dynamically created database无法将 Laravel 安装到动态创建的数据库
【发布时间】:2021-04-18 04:06:04
【问题描述】:

我正在尝试设置执行以下操作的工作流(必须在 CI 中工作,即在运行之前不存在任何内容):

  • 使用随机名称创建一个新数据库
  • 将我的 Laravel 应用程序的新实例安装到新的随机数据库名称
  • 运行我的测试
  • 测试完成后仍有测试数据库来调查问题
  • 不必处理 .env 文件或以任何方式编辑它们

编辑:建议让 Laravel Test 处理所有这些,因为它会擦除然后迁移您的数据库,但如果我理解正确,这假设数据库已经存在,即。我必须手动创建数据库,将其设置在 .env 然后运行我的脚本来安装应用程序并运行测试。这不是理想的最终目标/工作流程。

我有一个 Artisan 命令(gist here,信任 this post 以获得一堆代码)似乎应该执行上述所有操作,但运行测试除外(不能走那么远)。您可以在要点或下方看到我尝试告诉命令要连接到哪个数据库的多种方式:

// $_ENV['DB_DATABASE'] = $dbname;
// $this->getLaravel()->environment(['DB_DATABASE' => $dbname]);
// $this->info('env: ' . $this->getLaravel()->environment('DB_DATABASE'));
// \Illuminate\Support\Env::enablePutenv();
// putenv('DB_DATABASE=' . $dbname);
// $this->info('env: ' . json_encode($_ENV));
// $this->call('config:clear');
config(['database.connections.' . $connection . '.database' => $dbname]);

我发现每次运行脚本时,无论我如何尝试告诉环境要使用什么数据库,它都会尝试安装在我的 中定义的现有开发环境之上.env 文件。我希望将php artisan install --ready 安装到新的随机命名的数据库中,以便随后使用该数据库运行测试。

但我发现,没有办法动态地告诉 Laravel 或 PHPUnit 使用什么数据库,所以这似乎毫无意义。但这是一个常见的用例。 Laravel 开发人员如何正常处理这个问题?设置数据库然后复制/编辑 .env 和 phpunit.xml 文件的节点脚本?在 CI 环境中完成这一切?我觉得我错过了什么。

编辑:我已经更新了要点,包括从 Yahya's answer below 建议的更改,这可以让事情按需要运行,在更改 config() 后运行 DB:reconnect($connection)

【问题讨论】:

  • 你想达到什么目的?为什么使用随机数据库名称? laravel 已经拥有 testingdatabase testing 的所有功能,可以处理数据库创建和其他内容
  • "将我的 Laravel 应用程序的新实例安装到新的随机数据库名称" - 你的意思是安装 Laravel,并将其配置为使用你的新随机数据库吗?为什么不让脚本更新磁盘上的.env
  • 您希望这是一个持久的更改吗?例如创建新数据库后,它会更改您的配置。还是你想让它根据运行时动态改变数据库。
  • 感谢所有快速回复! @brombeer,您指的是Run Tests In Parallel 部分吗?这听起来像是复制了一个现有数据库以用于每个正在运行的测试实例,这在我的情况下不起作用。
  • @Don'tPanic,添加了一些澄清细节。我的意思是php artisan install --ready 是随机创建的数据库。我可以复制我的 .env 文件,将 dev 移到一边,编辑测试 .env 文件以指向新的数据库,然后运行测试,然后清理,但这似乎很快就会咬我。有没有办法告诉php artisan 除了 .env 文件之外要使用哪些环境变量?

标签: database laravel continuous-integration


【解决方案1】:

如果您想在运行时更改配置,请使用:

config(["database.connections.{$connection}.database" => $dbname]);

但是,当您更改预先存在的连接时,DatabaseManager 可能已经使用旧配置创建了连接。因此,您可能需要运行以下命令:

DB::reconnect($connection);

如果它是未使用的全新连接,则不需要。即

config(["database.connections.{$connection}' => $connectionConfig]);

如果您想选择使用哪个数据库连接,只需执行以下操作:

DB::connection($connectionName)->where('what_ever', 20)->...->get()

或者像这样更改您的默认连接:

DB::setDefaultConnection($connectionName);
DB::where('whaterver', 20)->...->get()

以下不起作用的原因是:

// You shouldn't be changing env variables during runtime, especially if config is cached
$_ENV['DB_DATABASE'] = $dbname; 

// this function checks what environment your in. Correct usage $this->getLaravel()->environment('staging')
$this->getLaravel()->environment(['DB_DATABASE' => $dbname]); 
$this->info('env: ' . $this->getLaravel()->environment('DB_DATABASE'));

// This enables the the putenv adapter. You shouldn't be calling it for this.
\Illuminate\Support\Env::enablePutenv();

// putenv shouldn't be used in Laravel project
putenv('DB_DATABASE=' . $dbname);

// This should set the database for the config, but you need to make sure your using it. Note this change is not persistent.
config(['database.connections.' . $connection . '.database' => $dbname]);

【讨论】:

  • 这个答案不是假设 1. 数据库已经创建并且 2. 我在 config/database.php 中定义了一个数据库连接吗?这两种情况都不是。这是一个动态环境,在运行测试之前我无法知道。
  • 感谢代码注释。我理解很多你不应该做的事情。我分享了这一点,以展示我已经尝试过的所有不同的事情。在正常情况下,我会避免进行这些更改。您能否澄清此评论:> 但您需要确保您使用它是什么意思?在我的共享脚本的上下文中“使用它”会是什么样子?
  • 如果这只是为了测试,你有没有看过Database Testing。当 Laravel 可以重置数据库时,我不确定为什么需要动态创建和设置数据库。
  • 有几件事在那里不起作用: 1. 假设数据库存在。想象一下这是一个 CI 环境,您必须在其中启动整个应用生态系统。 2. 它吹走了旧的测试数据库,我会在某些时候想要参考 3。...我以为有第三个,但我现在不记得了...
  • 轰隆隆!做到了,叶海亚!太感谢了!这让我发疯了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-19
  • 1970-01-01
  • 2014-06-02
  • 1970-01-01
  • 2021-06-03
  • 1970-01-01
相关资源
最近更新 更多