Skip to content

Issues with php artisan migrate:fresh affecting multiple database connections #55194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
piotrczech opened this issue Mar 28, 2025 · 7 comments

Comments

@piotrczech
Copy link

Laravel Version

12.1.1

PHP Version

laravelsail 8.4

Database Driver & Version

laravelsail mariadb:11

Description

I encountered a problem when using Laravel (with Sail) with multiple database connections. Specifically, when I run the sail artisan migrate:fresh command, it only drops tables from the main database (as expected), but it also runs migrations for additional connections, such as the conB connection, even when I specify a particular connection using the --database flag.

Problem overview

In my Laravel project, I have configured multiple database connections in config/database.php (based on this), including a main database (mariadb) and a secondary connection (conB), using Schema::connection('conB')->create(...) in my migrations.

When running the command:

sail artisan migrate:fresh --database=mariadb

or just

sail artisan migrate:fresh

I expect that only the migrations for the mariadb connection will run and the conB connection will remain unaffected. However, the migrations for conB are also being executed, despite explicitly specifying the database connection to use.
This leads to an issue where the secondary database connection (conB) is being migrated, even though it wasn't intended to be part of the migrate:fresh command and throw an error SQLSTATE[42S01]: Base table or view already exists: 1050 Table.

Proposed solution

The issue might stem from how Laravel handles migrations across multiple database connections in commands like migrate:fresh. Ideally, when specifying the --database flag, Laravel should restrict the migration process to that specific connection and not trigger migrations for any other database connection, such as conB.

Steps To Reproduce

Steps to reproduce: https://laracasts.com/discuss/channels/laravel/how-to-correctly-use-multiple-databases-on-the-same-connection-in-laravel

I followed this tutorial step by step

@piotrczech
Copy link
Author

piotrczech commented Mar 28, 2025

I think this topic https://stackoverflow.com/questions/72151051/run-migration-for-different-database-connections is also connected with this bug

Copy link

github-actions bot commented Apr 6, 2025

Thank you for reporting this issue!

As Laravel is an open source project, we rely on the community to help us diagnose and fix issues as it is not possible to research and fix every issue reported to us via GitHub.

If possible, please make a pull request fixing the issue you have described, along with corresponding tests. All pull requests are promptly reviewed by the Laravel team.

Thank you!

@piotrczech
Copy link
Author

@crynobone I don't think I need help, it's bug

@NiroDeveloper
Copy link

NiroDeveloper commented Apr 22, 2025

I think you just use the migration system wrong, it is not expected to use Schema::connection in the migration files.

Write the migrations from your secondary database in another directory or subdirectory, then call something like php artisan migrate:fresh --database=secondary --path=/my/other/migrations/

@piotrczech
Copy link
Author

piotrczech commented Apr 22, 2025

@NiroDeveloper Thanks for your suggestion! I really appreciate the thought, but in our setup we’re using the nWidart/laravel-modules package, so each module (and its migrations) lives in its own directory (and sometimes one module has multiple databases). I currently have >10 database connections, meaning with the --path approach you’d need >10 separate artisan commands just to refresh everything. That quickly becomes unmanageable.

I actually love the cleanness of the approach in the Laracasts article. Using Schema::connection() keeps each module’s tables tied to the right database in one place. Regular php artisan migrate works perfectly, since it runs all migrations as intended.

The real pain point is migrate:fresh (and by extension, use RefreshDatabase in tests): they only drop and rebuild the default connection. Migrations targeting other connections still run, but their old tables aren’t dropped first—leading to collisions when table names overlap, stale schemas in tests, and unpredictable failures.

It just feels inconsistent that artisan migrate handles this scenario gracefully, but migrate:fresh does not. Honestly, I haven't seen a better, more sensible approach to working with multiple databases (used for distinct models and domains) than the one in the article above—where Schema::connection() is naturally suggested and applied.

@NiroDeveloper
Copy link

NiroDeveloper commented Apr 23, 2025

The problem is that artisan db:wipe does not know which databases to drop, it is possible that some configured connections only exist in specific environments or do not really exist / are connected.
So you have to tell the application in some way, which databases it should drop.

artisan migrate only handles it correct, because you explicitly write Schema::connection into every migration.
(Also i do not like this approach, because only one __migrations table exists in your default database)
So i would say you already made a workaround for artisan migrate that does not work for artisan migrate:fresh.

Personally i fixed this problem by overwriting the command so it calls migrate:fresh multiple times for every database i have.
And yes a feature for this would be perfect, but laravel currently does not support multiple databases very well in multiple situations.

Also do not forget to set $connectionsToTransact in your test case, if you use a database testing trait.

@piotrczech
Copy link
Author

@NiroDeveloper thank you for your detailed explanation!

The problem is that artisan db:wipe does not know which databases to drop

I see now that the real blocker is db:wipe (and thus migrate:fresh) operates only on the default connection, not that the migrations table happens to live there. Laravel never records which other connections ran migrations, so it simply can’t drop them.

Personally i fixed this problem by overwriting the command

I’ve done the same—overriding migrate:fresh to loop through all eleven connections (drop → migrate). It works, but it feels like burying the problem under a patch instead of fixing it in the framework. Since Laravel is open source, I’d love to help drive a proper solution, but we need a clear direction first.

Here are three ideas I haven’t seen fully explored yet:

  • Define connections in config
    Add a new config key listing all connections that should be considered by migrate:fresh/db:wipe. This way projects can declaratively control which databases to include without extra flags or custom commands.

  • Track connection per migration
    Add a connection column to the migrations table (or support separate migrations tables per connection) so that db:wipe/migrate:fresh can read exactly which databases to reset.

  • Introduce an “include connections” flag
    Add something like --include-connections (or --all-connections) so that migrate, migrate:fresh, and db:wipe all drop & rebuild every connection involved in the project without hacks or multiple commands.

You also mentioned:

Also do not forget to set $connectionsToTransact in your test case, if you use a database testing trait.

Could you expand on that? Are you suggesting wrapping each DB connection in a transaction (instead of rebuilding schemas) and rolling them back after tests? I’ve been using RefreshDatabase (and sometimes an in-memory SQLite setup where tables are namespaced like database__table) to simulate multiple databases locally—while our CI/CD pipeline remains on MySQL/MariaDB.

Thanks again for your insights—this feels more like a small enhancement or bugfix than a “help wanted” question @crynobone. If we can agree on an approach, I’d be happy to draft a PoC or open a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants