src/RocknRoot/StrayFw/Database/Postgres/Migration.php
public static function rollback(array $mapping)
    {
        $database = Database::get($mapping['config']['database']);
        $database->beginTransaction();
        if (self::ensureTable($mapping) === false) {
            $database->rollBack();
            return;
        }
        $migrations = Config::get(rtrim($mapping['config']['migrations']['path'], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'migrations.yml');
        $select = new Select($mapping['config']['database'], true);
        $select->select('*')
            ->where('migration IS NOT NULL')
            ->from('_stray_migration')
            ->orderBy('date DESC')
            ->limit(1);
        if ($select->execute() === false) {
            echo 'Can\'t fetch from _stray_migration (' . $select->getErrorMessage() . ')' . PHP_EOL;
            $database->rollBack();
            return;
        }
        $last = $select->fetch();
        if (!$last) {
            echo 'There is no executed migration.' . PHP_EOL;
            $database->rollBack();
            return;
        }
        echo 'Last executed migration is: ' . $last['migration'] . '.' . PHP_EOL;
        $last['date'] = new \DateTime($last['date']);
        $last['date'] = $last['date']->getTimestamp();
        $migration = null;
        $i = 0;
        $imax = count($migrations);
        while ($i < $imax) {
            if ($migrations[$i]['name'] == $last['migration']) {
                $migration = $migrations[$i];
                break;
            }
            $i++;
        }
        if ($migration == null) {
            echo 'Can\'t find migration in migrations.yml.' . PHP_EOL;
            return;
        }
        $cl = '\\' . ltrim(rtrim($mapping['config']['migrations']['namespace'], '\\'), '\\') . '\\' . ucfirst($migration['name']) . '\\' . ucfirst($migration['name']);
        if ($i < $imax - 1) {
            $schema = Config::get(rtrim($mapping['config']['migrations']['path'], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . ucfirst($migrations[$i + 1]['name']) . DIRECTORY_SEPARATOR . 'schema.yml');
        } else {
            $schema = Config::get($mapping['config']['schema']);
            echo'last';
        }
        $n = new $cl($schema, rtrim($mapping['config']['migrations']['path'], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . ucfirst($migration['name']) . DIRECTORY_SEPARATOR);
        try {
            $n->down();
        } catch (Exception $e) {
            $database->rollBack();
            throw $e;
        }
        $delete = new Delete($mapping['config']['database']);
        $delete->from('_stray_migration');
        $delete->bind('migration', $migration['name']);
        $delete->where([ 'migration' => ':migration' ]);
        if ($delete->execute() === false) {
            echo 'Can\'t delete from _stray_migration (' . $delete->getErrorMessage() . ')' . PHP_EOL;
            $database->rollBack();
            return;
        }
        $database->commit();
    }
public static function rollback(array $mapping)
    {
        $database = Database::get($mapping['config']['database']);
        $database->beginTransaction();
        if (self::ensureTable($mapping) === false) {
            $database->rollBack();
            return;
        }
        $migrations = Config::get(rtrim($mapping['config']['migrations']['path'], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'migrations.yml');
        $select = new Select($mapping['config']['database'], true);
        $select->select('*')
            ->where('migration IS NOT NULL')
            ->from('_stray_migration')
            ->orderBy('date DESC')
            ->limit(1);
        if ($select->execute() === false) {
            echo 'Can\'t fetch from _stray_migration (' . $select->getErrorMessage() . ')' . PHP_EOL;
            $database->rollBack();
            return;
        }
        $last = $select->fetch();
        if (!$last) {
            echo 'There is no executed migration.' . PHP_EOL;
            $database->rollBack();
            return;
        }
        echo 'Last executed migration is: ' . $last['migration'] . '.' . PHP_EOL;
        $last['date'] = new \DateTime($last['date']);
        $last['date'] = $last['date']->getTimestamp();
        $migration = null;
        $i = 0;
        $imax = count($migrations);
        while ($i < $imax) {
            if ($migrations[$i]['name'] == $last['migration']) {
                $migration = $migrations[$i];
                break;
            }
            $i++;
        }
        if ($migration == null) {
            echo 'Can\'t find migration in migrations.yml.' . PHP_EOL;
            return;
        }
        $cl = '\\' . ltrim(rtrim($mapping['config']['migrations']['namespace'], '\\'), '\\') . '\\' . ucfirst($migration['name']) . '\\' . ucfirst($migration['name']);
        if ($i < $imax - 1) {
            $schema = Config::get(rtrim($mapping['config']['migrations']['path'], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . ucfirst($migrations[$i + 1]['name']) . DIRECTORY_SEPARATOR . 'schema.yml');
        } else {
            $schema = Config::get($mapping['config']['schema']);
            echo'last';
        }
        $n = new $cl($schema, rtrim($mapping['config']['migrations']['path'], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . ucfirst($migration['name']) . DIRECTORY_SEPARATOR);
        try {
            $n->down();
        } catch (Exception $e) {
            $database->rollBack();
            throw $e;
        }
        $delete = new Delete($mapping['config']['database']);
        $delete->from('_stray_migration');
        $delete->bind('migration', $migration['name']);
        $delete->where([ 'migration' => ':migration' ]);
        if ($delete->execute() === false) {
            echo 'Can\'t delete from _stray_migration (' . $delete->getErrorMessage() . ')' . PHP_EOL;
            $database->rollBack();
            return;
        }
        $database->commit();
    }
Run reversed migration code for specified mapping.

@param array $mapping mapping definition