/** * Rollback the open database transaction */ public function rollback() { if ($this->transactionDepth === 1) { $this->connection->rollback(); } $this->transactionDepth -= 1; return $this; }
/** * @param int $version target migration version, if not set all not applied available migrations will be applied * @param bool $force force apply migration * @param bool $down rollback migration * @throws MigrationException */ public function migrate($version = null, $force = false, $down = false) { $migrations = $this->getMigrationClasses($force); if (!is_null($version) && !$this->hasMigrationVersions($migrations, $version)) { echo sprintf('Migration version %s is not found!', $version); return true; // throw new MigrationException(sprintf('Migration version %s is not found!', $version)); } $currentMigrationVersion = $this->migrationVersionTable->getCurrentVersion($this->migrationsDirMd5); if (!is_null($version) && $version == $currentMigrationVersion && !$force) { throw new MigrationException(sprintf('Migration version %s is current version!', $version)); } $this->connection->beginTransaction(); try { if ($version && $force) { foreach ($migrations as $migration) { if ($migration['version'] == $version) { // if existing migration is forced to apply - delete its information from migrated // to avoid duplicate key error if (!$down) { $this->migrationVersionTable->delete($migration['version'], $this->migrationsDirMd5); } $this->applyMigration($migration, $down); break; } } // target migration version not set or target version is greater than last applied migration -> apply migrations } elseif (is_null($version) || !is_null($version) && $version > $currentMigrationVersion) { foreach ($migrations as $migration) { if ($migration['version'] > $currentMigrationVersion) { if (is_null($version) || !is_null($version) && $version >= $migration['version']) { $this->applyMigration($migration); } } } // target migration version is set -> rollback migration } elseif (!is_null($version) && $version < $currentMigrationVersion) { $migrationsByDesc = $this->sortMigrationsByVersionDesc($migrations); foreach ($migrationsByDesc as $migration) { if ($migration['version'] > $version && $migration['version'] <= $currentMigrationVersion) { $this->applyMigration($migration, true); } } } $this->connection->commit(); } catch (InvalidQueryException $e) { $this->connection->rollback(); $msg = sprintf('%s: "%s"; File: %s; Line #%d', $e->getMessage(), $e->getPrevious()->getMessage(), $e->getFile(), $e->getLine()); throw new MigrationException($msg); } catch (\Exception $e) { $this->connection->rollback(); $msg = sprintf('%s; File: %s; Line #%d', $e->getMessage(), $e->getFile(), $e->getLine()); throw new MigrationException($msg); } }
protected function applyMigration(array $migration, $down = false, $fake = false) { $this->connection->beginTransaction(); try { /** @var $migrationObject AbstractMigration */ $migrationObject = new $migration['class']($this->metadata, $this->outputWriter); if ($migrationObject instanceof ServiceLocatorAwareInterface) { if (is_null($this->serviceLocator)) { throw new \RuntimeException(sprintf('Migration class %s requires a ServiceLocator, but there is no instance available.', get_class($migrationObject))); } $migrationObject->setServiceLocator($this->serviceLocator); } if ($migrationObject instanceof AdapterAwareInterface) { if (is_null($this->adapter)) { throw new \RuntimeException(sprintf('Migration class %s requires an Adapter, but there is no instance available.', get_class($migrationObject))); } $migrationObject->setDbAdapter($this->adapter); } $this->outputWriter->writeLine(sprintf("%sExecute migration class %s %s", $fake ? '[FAKE] ' : '', $migration['class'], $down ? 'down' : 'up')); if (!$fake) { $sqlList = $down ? $migrationObject->getDownSql() : $migrationObject->getUpSql(); foreach ($sqlList as $sql) { $this->outputWriter->writeLine("Execute query:\n\n" . $sql); $this->connection->execute($sql); } } if ($down) { $this->migrationVersionTable->delete($migration['version']); } else { $this->migrationVersionTable->save($migration['version'], $migration['source']); } $this->connection->commit(); } catch (InvalidQueryException $e) { $this->connection->rollback(); $previousMessage = $e->getPrevious() ? $e->getPrevious()->getMessage() : null; $msg = sprintf('%s: "%s"; File: %s; Line #%d', $e->getMessage(), $previousMessage, $e->getFile(), $e->getLine()); throw new MigrationException($msg, $e->getCode(), $e); } catch (\Exception $e) { $this->connection->rollback(); $msg = sprintf('%s; File: %s; Line #%d', $e->getMessage(), $e->getFile(), $e->getLine()); throw new MigrationException($msg, $e->getCode(), $e); } }
protected function tearDown() { $this->connection->rollback(); unset($this->mapper); unset($this->connection); }