Laravel 10如何通过迁移自动创建PostgreSQL测试数据库?
Laravel通过主数据库连接创建PostgreSQL测试库的解决方案
问题描述
我正在为Laravel搭建环境,需要在一台PostgreSQL服务器上配置两个数据库:生产库名为laravel,测试/开发库名为laravel_test。尝试通过Laravel数据库迁移创建新数据库,使用了以下代码:
$dbName = config("database.connections.pgsql-test.database"); // Create the second database DB::statement("CREATE DATABASE $dbName");
但出现错误:
SQLSTATE[25001]: Active sql transaction: 7 ERROR: CREATE DATABASE cannot run inside a transaction block (Connection: pgsql, SQL: CREATE DATABASE laravel_test)
现有主数据库连接pgsql配置:
'pgsql' => [ 'driver' => 'pgsql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '5432'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', 'prefix_indexes' => true, 'search_path' => 'public', 'sslmode' => 'prefer', ],
测试库连接pgsql-test配置:
'pgsql-test' => [ 'driver' => 'pgsql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '5432'), 'database' => env('DB_DATABASE', 'forge') . "_test", 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', 'prefix_indexes' => true, 'search_path' => 'public', 'sslmode' => 'prefer', ],
能否通过主数据库连接创建新数据库,无需手动创建即可使用pgsql-test连接?
解决方案
核心问题原因
PostgreSQL的CREATE DATABASE命令不能在事务块内执行,而Laravel默认会为迁移操作开启事务,直接在迁移里执行这条语句就会触发错误。
实现步骤
绕过事务执行创建命令
利用Laravel的unprepared()方法绕过事务包装,直接通过主连接执行创建语句:$dbName = config("database.connections.pgsql-test.database"); // 使用主连接执行无事务的SQL DB::connection('pgsql')->unprepared("CREATE DATABASE $dbName");先验证再创建,避免重复报错
先查询数据库是否存在,不存在再执行创建:$dbName = config("database.connections.pgsql-test.database"); $exists = DB::connection('pgsql')->select("SELECT 1 FROM pg_database WHERE datname = ?", [$dbName]); if (empty($exists)) { DB::connection('pgsql')->unprepared("CREATE DATABASE $dbName"); }推荐:封装为Artisan命令
创建自定义Artisan命令统一管理测试库创建逻辑,比如db:create-test:// app/Console/Commands/CreateTestDatabase.php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; class CreateTestDatabase extends Command { protected $signature = 'db:create-test'; protected $description = '创建Laravel测试数据库'; public function handle() { $dbName = config("database.connections.pgsql-test.database"); $exists = DB::connection('pgsql')->select("SELECT 1 FROM pg_database WHERE datname = ?", [$dbName]); if (empty($exists)) { DB::connection('pgsql')->unprepared("CREATE DATABASE $dbName"); $this->info("数据库 $dbName 创建成功!"); } else { $this->info("数据库 $dbName 已存在。"); } } }注册命令后,执行
php artisan db:create-test即可完成测试库创建。
注意事项
- 确保主连接的数据库用户拥有创建数据库的权限,否则会触发权限不足错误。
- 不要在迁移文件中处理数据库创建逻辑,迁移的核心职责是管理表结构变更,数据库创建属于环境初始化操作。
内容的提问来源于stack exchange,提问作者Erikas
相关产品推荐
相关产品推荐

