自定义 laravel 迁移命令“[Illuminate\Database\Migrations\MigrationRepositoryInterface] 不可实例化”
Custom laravel migration command "[Illuminate\Database\Migrations\MigrationRepositoryInterface] is not instantiable"
我正在尝试创建一个自定义 laravel (5.2) 迁移命令,该命令基本上与 migrate:status
的工作方式相同,只是它只列出待处理的迁移而不是所有迁移。
为此,我非常简单地将 migrate:status
复制到我的 app/console 目录中的另一个 class 中,并调整代码以满足我的需要。但是,每当我尝试 运行 时,我都会收到错误消息:
[Illuminate\Contracts\Container\BindingResolutionException]
Target [Illuminate\Database\Migrations\MigrationRepositoryInterface] is not instantiable while building [App\Console\Commands\PendingMigrations, Illuminate\Database\Migrations\Migrator].
class 本身和 fire()
方法的内容似乎并不重要,因为它没有达到那么远,它在 __construct()
方法中失败。
<?php namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Database\Migrations\Migrator;
class PendingMigrations extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'migrate:pending';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Shows a list of pending migrations';
/**
* The migrator instance.
*
* @var \Illuminate\Database\Migrations\Migrator
*/
protected $migrator;
/**
* Create a new migration rollback command instance.
*
* @param \Illuminate\Database\Migrations\Migrator $migrator
* @return \Illuminate\Database\Console\Migrations\StatusCommand
*/
public function __construct(Migrator $migrator)
{
parent::__construct();
$this->migrator = $migrator;
}
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
}
}
原因可能与 IoC 容器和加载顺序有关,但我对 Laravel 的内部工作原理了解不够,无法弄清楚任何问题不止于此。
一定可以吧?
我目前卡在 5.2 上,所以我不确定这个问题是否在更新的版本中存在。
到目前为止,我唯一尝试过的是将迁移服务提供商添加到 config/app.php
列表的顶部,但它似乎没有影响,无论如何这只是一个随机猜测.
providers' => [
Illuminate\Database\MigrationServiceProvider::class,`
]
我使用以下方法解决了这个问题:
$this->migrator = app('migrator');
但这不一定是最好的方法
Migrator
实例未绑定到 IoC 容器中的 class 名称,它绑定到 migrator
别名。
来自Illuminate\Database\MigrationServiceProvider
:
/**
* Register the migrator service.
*
* @return void
*/
protected function registerMigrator()
{
// The migrator is responsible for actually running and rollback the migration
// files in the application. We'll pass in our database connection resolver
// so the migrator can resolve any of these connections when it needs to.
$this->app->singleton('migrator', function ($app) {
$repository = $app['migration.repository'];
return new Migrator($repository, $app['db'], $app['files']);
});
}
由于 class 名称未绑定在 IoC 容器中,当 Laravel 解析您的命令并尝试解析 Migrator
依赖项时,它会尝试从scratch 并失败,因为 Illuminate\Database\Migrations\MigrationRepositoryInterface
也未绑定在 IoC 容器中(因此您收到错误)。
由于 Laravel 自己无法解决这个问题,您需要为 Migrator
class 名称注册绑定,或者您需要为您的命令注册绑定. Laravel 本身注册了 Illuminate\Foundation\Providers\ArtisanServiceProvider
中命令的所有绑定。 command.migrate
绑定的示例:
/**
* Register the command.
*
* @return void
*/
protected function registerMigrateCommand()
{
$this->app->singleton('command.migrate', function ($app) {
return new MigrateCommand($app['migrator']);
});
}
因此,在您的 AppServiceProvider
或您设置的其他服务提供商中,您可以添加以下内容之一:
在 IoC 中注册命令:
$this->app->singleton(\App\Console\Commands\PendingMigrations::class, function ($app) {
return new \App\Console\Commands\PendingMigrations($app['migrator']);
});
或者,在 IoC 中注册 Migrator class 名称:
$this->app->singleton(\Illuminate\Database\Migrations\Migrator::class, function ($app) {
return $app['migrator'];
});
因为我不想在应用程序的任何地方注册 migrator
,但我仍然想扩展 MigrateCommand
本身,所以我想出了这种方法来维护我的应用程序是:
public function __construct()
{
app()->singleton(\App\Console\Commands\PendingMigrations::class, function ($app) {
return new \App\Console\Commands\PendingMigrations($app['migrator']);
});
parent::__construct(app('migrator'));
}
我正在尝试创建一个自定义 laravel (5.2) 迁移命令,该命令基本上与 migrate:status
的工作方式相同,只是它只列出待处理的迁移而不是所有迁移。
为此,我非常简单地将 migrate:status
复制到我的 app/console 目录中的另一个 class 中,并调整代码以满足我的需要。但是,每当我尝试 运行 时,我都会收到错误消息:
[Illuminate\Contracts\Container\BindingResolutionException] Target [Illuminate\Database\Migrations\MigrationRepositoryInterface] is not instantiable while building [App\Console\Commands\PendingMigrations, Illuminate\Database\Migrations\Migrator].
class 本身和 fire()
方法的内容似乎并不重要,因为它没有达到那么远,它在 __construct()
方法中失败。
<?php namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Database\Migrations\Migrator;
class PendingMigrations extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'migrate:pending';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Shows a list of pending migrations';
/**
* The migrator instance.
*
* @var \Illuminate\Database\Migrations\Migrator
*/
protected $migrator;
/**
* Create a new migration rollback command instance.
*
* @param \Illuminate\Database\Migrations\Migrator $migrator
* @return \Illuminate\Database\Console\Migrations\StatusCommand
*/
public function __construct(Migrator $migrator)
{
parent::__construct();
$this->migrator = $migrator;
}
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
}
}
原因可能与 IoC 容器和加载顺序有关,但我对 Laravel 的内部工作原理了解不够,无法弄清楚任何问题不止于此。
一定可以吧?
我目前卡在 5.2 上,所以我不确定这个问题是否在更新的版本中存在。
到目前为止,我唯一尝试过的是将迁移服务提供商添加到 config/app.php
列表的顶部,但它似乎没有影响,无论如何这只是一个随机猜测.
providers' => [
Illuminate\Database\MigrationServiceProvider::class,`
]
我使用以下方法解决了这个问题:
$this->migrator = app('migrator');
但这不一定是最好的方法
Migrator
实例未绑定到 IoC 容器中的 class 名称,它绑定到 migrator
别名。
来自Illuminate\Database\MigrationServiceProvider
:
/**
* Register the migrator service.
*
* @return void
*/
protected function registerMigrator()
{
// The migrator is responsible for actually running and rollback the migration
// files in the application. We'll pass in our database connection resolver
// so the migrator can resolve any of these connections when it needs to.
$this->app->singleton('migrator', function ($app) {
$repository = $app['migration.repository'];
return new Migrator($repository, $app['db'], $app['files']);
});
}
由于 class 名称未绑定在 IoC 容器中,当 Laravel 解析您的命令并尝试解析 Migrator
依赖项时,它会尝试从scratch 并失败,因为 Illuminate\Database\Migrations\MigrationRepositoryInterface
也未绑定在 IoC 容器中(因此您收到错误)。
由于 Laravel 自己无法解决这个问题,您需要为 Migrator
class 名称注册绑定,或者您需要为您的命令注册绑定. Laravel 本身注册了 Illuminate\Foundation\Providers\ArtisanServiceProvider
中命令的所有绑定。 command.migrate
绑定的示例:
/**
* Register the command.
*
* @return void
*/
protected function registerMigrateCommand()
{
$this->app->singleton('command.migrate', function ($app) {
return new MigrateCommand($app['migrator']);
});
}
因此,在您的 AppServiceProvider
或您设置的其他服务提供商中,您可以添加以下内容之一:
在 IoC 中注册命令:
$this->app->singleton(\App\Console\Commands\PendingMigrations::class, function ($app) {
return new \App\Console\Commands\PendingMigrations($app['migrator']);
});
或者,在 IoC 中注册 Migrator class 名称:
$this->app->singleton(\Illuminate\Database\Migrations\Migrator::class, function ($app) {
return $app['migrator'];
});
因为我不想在应用程序的任何地方注册 migrator
,但我仍然想扩展 MigrateCommand
本身,所以我想出了这种方法来维护我的应用程序是:
public function __construct()
{
app()->singleton(\App\Console\Commands\PendingMigrations::class, function ($app) {
return new \App\Console\Commands\PendingMigrations($app['migrator']);
});
parent::__construct(app('migrator'));
}