I'm creating a package and want to override the Migrate command but cannot seem to figure out how. It seems like Laravel itself is getting a higher priority over my ServiceProvider, is there a way to gain priority in the override and get my custom class in there via a package?
2 Answers
I tried to use a ServiceProvider
's register()
method to bind a custom implementation of Illuminate\Database\Migrations\Migrator
but it didn't work.
Although this is not pretty, I suppose you could use composer
to autoload your custom implementation of whatever classes you need to override.
For example, let's say you want to override Illuminate\Database\Migrations\Migrator
.
Write a new implementation of this class and save somewhere... for example in app/Overrides/Illuminate/Database/Migrations/Migrator.php
.
Inside this file, override the vendor class keeping the vendor namespace.
// app/Overrides/Illuminate/Database/Migrations/Migrator.php
namespace Illuminate/Database/Migrations;
class Migrator
{
....
}
Then, in your composer.json
file, you need to explicitly state you want THIS class to be autoloaded instead of laravel's, and also exclude laravel's own class from the autoloading.
"autoload": {
...
"exclude-from-classmap": ["vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php"],
"files": ["app/Overrides/Illuminate/Database/Migrations/Migrator.php"]
...
},
And finally, run composer dumpautoload
. And run it again every time you add a new package with composer require
.

- 14,160
- 4
- 26
- 43
-
It's not the prettiest but I feel like it's better than copying all migrate commands... – K1ll3rM Apr 21 '23 at 07:06
-
1https://github.com/laravel/framework/issues/46843 Apparently it's not considered a bug, just not supported at all. – K1ll3rM Apr 21 '23 at 07:46
-
I figured it out and added it as an answer, hope it helps someone in the future. – K1ll3rM Apr 21 '23 at 08:21
I found out why the replace wasn't working, the original service provider is deferred, meaning it's register and boot methods get called just before the MigrateCommand class is needed. When I deferred my service provider the same way it started to work!
class MigrateServiceProvider extends ServiceProvider implements DeferrableProvider
{
public function register(): void
{
$this->app->scoped(Migrator::class, function(Application $app) {
return $app->make('migrator');
});
}
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->commands([
NewMigrateCommand::class
]);
}
}
public function provides(): array
{
return [NewMigrateCommand::class, Migrator::class];
}
}

- 169
- 8
-
-
@IGP Do note that this feature seems to be unsupported by Laravel, I don't see any reason for this to break though, unless they make some major changes to how commands work. – K1ll3rM Apr 21 '23 at 09:26