/** * @param Schema $fromSchema * @return Schema */ public function createToSchema(Schema $fromSchema) { $originalSchemaManipulator = $this->originalSchemaManipulator; if ($fromSchema instanceof LazyLoadingInterface && !$fromSchema->isProxyInitialized()) { return $this->proxyFactory->createProxy(Schema::class, function (&$wrappedObject, $proxy, $method, array $parameters, &$initializer) use($originalSchemaManipulator, $fromSchema) { $initializer = null; $wrappedObject = $originalSchemaManipulator->createToSchema($fromSchema); return true; }); } return $this->originalSchemaManipulator->createToSchema($fromSchema); }
/** * Execute this migration version up or down and and return the SQL. * We are only allowing the addSql call and the schema modification to take effect in the up and down call. * This is necessary to ensure that the migration is revertable. * The schema is passed to the pre and post method only to be able to test the presence of some table, And the * connection that can get used trough it allow for the test of the presence of records. * * @param string $direction The direction to execute the migration. * @param boolean $dryRun Whether to not actually execute the migration SQL and just do a dry run. * @param boolean $timeAllQueries Measuring or not the execution time of each SQL query. * * @return array $sql * * @throws \Exception when migration fails */ public function execute($direction, $dryRun = false, $timeAllQueries = false) { $this->sql = []; $transaction = $this->migration->isTransactional(); if ($transaction) { //only start transaction if in transactional mode $this->connection->beginTransaction(); } try { $migrationStart = microtime(true); $this->state = self::STATE_PRE; $fromSchema = $this->schemaProvider->createFromSchema(); $this->migration->{'pre' . ucfirst($direction)}($fromSchema); if ($direction === self::DIRECTION_UP) { $this->outputWriter->write("\n" . sprintf(' <info>++</info> migrating <comment>%s</comment>', $this->version) . "\n"); } else { $this->outputWriter->write("\n" . sprintf(' <info>--</info> reverting <comment>%s</comment>', $this->version) . "\n"); } $this->state = self::STATE_EXEC; $toSchema = $this->schemaProvider->createToSchema($fromSchema); $this->migration->{$direction}($toSchema); $this->addSql($this->schemaProvider->getSqlDiffToMigrate($fromSchema, $toSchema)); $this->executeRegisteredSql($dryRun, $timeAllQueries); $this->state = self::STATE_POST; $this->migration->{'post' . ucfirst($direction)}($toSchema); if (!$dryRun) { if ($direction === self::DIRECTION_UP) { $this->markMigrated(); } else { $this->markNotMigrated(); } } $migrationEnd = microtime(true); $this->time = round($migrationEnd - $migrationStart, 2); if ($direction === self::DIRECTION_UP) { $this->outputWriter->write(sprintf("\n <info>++</info> migrated (%ss)", $this->time)); } else { $this->outputWriter->write(sprintf("\n <info>--</info> reverted (%ss)", $this->time)); } if ($transaction) { //commit only if running in transactional mode $this->connection->commit(); } $this->state = self::STATE_NONE; return $this->sql; } catch (SkipMigrationException $e) { if ($transaction) { //only rollback transaction if in transactional mode $this->connection->rollBack(); } if ($dryRun === false) { // now mark it as migrated if ($direction === self::DIRECTION_UP) { $this->markMigrated(); } else { $this->markNotMigrated(); } } $this->outputWriter->write(sprintf("\n <info>SS</info> skipped (Reason: %s)", $e->getMessage())); $this->state = self::STATE_NONE; return []; } catch (\Exception $e) { $this->outputWriter->write(sprintf('<error>Migration %s failed during %s. Error %s</error>', $this->version, $this->getExecutionState(), $e->getMessage())); if ($transaction) { //only rollback transaction if in transactional mode $this->connection->rollBack(); } $this->state = self::STATE_NONE; throw $e; } }