Blame | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace Illuminate\Database\Console\Migrations;use Illuminate\Console\ConfirmableTrait;use Illuminate\Contracts\Console\Isolatable;use Illuminate\Contracts\Events\Dispatcher;use Illuminate\Database\Events\SchemaLoaded;use Illuminate\Database\Migrations\Migrator;use Illuminate\Database\SQLiteDatabaseDoesNotExistException;use Illuminate\Database\SqlServerConnection;use PDOException;use Throwable;class MigrateCommand extends BaseCommand implements Isolatable{use ConfirmableTrait;/*** The name and signature of the console command.** @var string*/protected $signature = 'migrate {--database= : The database connection to use}{--force : Force the operation to run when in production}{--path=* : The path(s) to the migrations files to be executed}{--realpath : Indicate any provided migration file paths are pre-resolved absolute paths}{--schema-path= : The path to a schema dump file}{--pretend : Dump the SQL queries that would be run}{--seed : Indicates if the seed task should be re-run}{--seeder= : The class name of the root seeder}{--step : Force the migrations to be run so they can be rolled back individually}';/*** The console command description.** @var string*/protected $description = 'Run the database migrations';/*** The migrator instance.** @var \Illuminate\Database\Migrations\Migrator*/protected $migrator;/*** The event dispatcher instance.** @var \Illuminate\Contracts\Events\Dispatcher*/protected $dispatcher;/*** Create a new migration command instance.** @param \Illuminate\Database\Migrations\Migrator $migrator* @param \Illuminate\Contracts\Events\Dispatcher $dispatcher* @return void*/public function __construct(Migrator $migrator, Dispatcher $dispatcher){parent::__construct();$this->migrator = $migrator;$this->dispatcher = $dispatcher;}/*** Execute the console command.** @return int*/public function handle(){if (! $this->confirmToProceed()) {return 1;}$this->migrator->usingConnection($this->option('database'), function () {$this->prepareDatabase();// Next, we will check to see if a path option has been defined. If it has// we will use the path relative to the root of this installation folder// so that migrations may be run for any path within the applications.$migrations = $this->migrator->setOutput($this->output)->run($this->getMigrationPaths(), ['pretend' => $this->option('pretend'),'step' => $this->option('step'),]);// Finally, if the "seed" option has been given, we will re-run the database// seed task to re-populate the database, which is convenient when adding// a migration and a seed at the same time, as it is only this command.if ($this->option('seed') && ! $this->option('pretend')) {$this->call('db:seed', ['--class' => $this->option('seeder') ?: 'Database\\Seeders\\DatabaseSeeder','--force' => true,]);}});return 0;}/*** Prepare the migration database for running.** @return void*/protected function prepareDatabase(){if (! $this->repositoryExists()) {$this->components->info('Preparing database.');$this->components->task('Creating migration table', function () {return $this->callSilent('migrate:install', array_filter(['--database' => $this->option('database'),])) == 0;});$this->newLine();}if (! $this->migrator->hasRunAnyMigrations() && ! $this->option('pretend')) {$this->loadSchemaState();}}/*** Determine if the migrator repository exists.** @return bool*/protected function repositoryExists(){return retry(2, fn () => $this->migrator->repositoryExists(), 0, function ($e) {try {if ($e->getPrevious() instanceof SQLiteDatabaseDoesNotExistException) {return $this->createMissingSqliteDatbase($e->getPrevious()->path);}$connection = $this->migrator->resolveConnection($this->option('database'));if ($e->getPrevious() instanceof PDOException &&$e->getPrevious()->getCode() === 1049 &&$connection->getDriverName() === 'mysql') {return $this->createMissingMysqlDatabase($connection);}return false;} catch (Throwable) {return false;}});}/*** Create a missing SQLite database.** @param string $path* @return bool*/protected function createMissingSqliteDatbase($path){if ($this->option('force')) {return touch($path);}if ($this->option('no-interaction')) {return false;}$this->components->warn('The SQLite database does not exist: '.$path);if (! $this->components->confirm('Would you like to create it?')) {return false;}return touch($path);}/*** Create a missing MySQL database.** @return bool*/protected function createMissingMysqlDatabase($connection){if ($this->laravel['config']->get("database.connections.{$connection->getName()}.database") !== $connection->getDatabaseName()) {return false;}if (! $this->option('force') && $this->option('no-interaction')) {return false;}if (! $this->option('force') && ! $this->option('no-interaction')) {$this->components->warn("The database '{$connection->getDatabaseName()}' does not exist on the '{$connection->getName()}' connection.");if (! $this->components->confirm('Would you like to create it?')) {return false;}}try {$this->laravel['config']->set("database.connections.{$connection->getName()}.database", null);$this->laravel['db']->purge();$freshConnection = $this->migrator->resolveConnection($this->option('database'));return tap($freshConnection->unprepared("CREATE DATABASE IF NOT EXISTS `{$connection->getDatabaseName()}`"), function () {$this->laravel['db']->purge();});} finally {$this->laravel['config']->set("database.connections.{$connection->getName()}.database", $connection->getDatabaseName());}}/*** Load the schema state to seed the initial database schema structure.** @return void*/protected function loadSchemaState(){$connection = $this->migrator->resolveConnection($this->option('database'));// First, we will make sure that the connection supports schema loading and that// the schema file exists before we proceed any further. If not, we will just// continue with the standard migration operation as normal without errors.if ($connection instanceof SqlServerConnection ||! is_file($path = $this->schemaPath($connection))) {return;}$this->components->info('Loading stored database schemas.');$this->components->task($path, function () use ($connection, $path) {// Since the schema file will create the "migrations" table and reload it to its// proper state, we need to delete it here so we don't get an error that this// table already exists when the stored database schema file gets executed.$this->migrator->deleteRepository();$connection->getSchemaState()->handleOutputUsing(function ($type, $buffer) {$this->output->write($buffer);})->load($path);});$this->newLine();// Finally, we will fire an event that this schema has been loaded so developers// can perform any post schema load tasks that are necessary in listeners for// this event, which may seed the database tables with some necessary data.$this->dispatcher->dispatch(new SchemaLoaded($connection, $path));}/*** Get the path to the stored schema for the given connection.** @param \Illuminate\Database\Connection $connection* @return string*/protected function schemaPath($connection){if ($this->option('schema-path')) {return $this->option('schema-path');}if (file_exists($path = database_path('schema/'.$connection->getName().'-schema.dump'))) {return $path;}return database_path('schema/'.$connection->getName().'-schema.sql');}}