@ -167,8 +173,8 @@ class MigrateController extends Controller
if ($this->confirm('Apply the above ' . ($n === 1 ? 'migration' : 'migrations') . "?")) {
foreach ($migrations as $migration) {
if ($this->migrateUp($migration) === false) {
echo "\nMigration failed. The rest of the new migrations are canceled.\n";
if (!$this->migrateUp($migration)) {
echo "\nMigration failed. The rest of the migrations are canceled.\n";
return;
}
}
@ -177,25 +183,26 @@ class MigrateController extends Controller
}
/**
* Downgrades the application by reverting old migrations. For example,
* Downgrades the application by reverting old migrations.
* For example,
*
* ~~~
* yiic migrate/down # revert the last migration
* yiic migrate/down 3 # revert the last 3 migrations
* ~~~
*
* @param array $args the number of migrations to be reverted. If not provided,
* the last applied migration will be reverted.
* @throws Exception if the number of the steps is less than 1.
* @param integer $limit the number of migrations to be reverted. Defaults to 1,
* meaning the last applied migration will be reverted.
* @throws Exception if the number of the steps specified is less than 1.
*/
public function actionDown($args)
public function actionDown($limit = 1)
{
$step = isset($args[0]) ? (int)$args[0] : 1;
if ($step<1){
throw new Exception("The step parameter must be greater than 0.");
$limit = (int)$limit;
if ($limit<1){
throw new Exception("The step argument must be greater than 0.");
}
if (($migrations = $this->getMigrationHistory($step)) === array()) {
if (($migrations = $this->getMigrationHistory($limit)) === array()) {
echo "No migration has been done before.\n";
return;
}
@ -210,8 +217,8 @@ class MigrateController extends Controller
if ($this->confirm('Revert the above ' . ($n === 1 ? 'migration' : 'migrations') . "?")) {
foreach ($migrations as $migration) {
if ($this->migrateDown($migration) === false) {
echo "\nMigration failed. All later migrations are canceled.\n";
if (!$this->migrateDown($migration)) {
echo "\nMigration failed. The rest of the migrations are canceled.\n";
return;
}
}
@ -219,14 +226,29 @@ class MigrateController extends Controller
}
}
public function actionRedo($args)
/**
* Redoes the last few migrations.
*
* This command will first revert the specified migrations, and then apply
* them again. For example,
*
* ~~~
* yiic migrate/redo # redo the last applied migration
* yiic migrate/redo 3 # redo the last 3 applied migrations
* ~~~
*
* @param integer $limit the number of migrations to be redone. Defaults to 1,
* meaning the last applied migration will be redone.
* @throws Exception if the number of the steps specified is less than 1.
*/
public function actionRedo($limit = 1)
{
$step = isset($args[0]) ? (int)$args[0] : 1;
if ($step <1){
die("Error: The step parameter must be greater than 0.\n");
$limit = (int)$limit;
if ($limit<1){
throw new Exception("The step argument must be greater than 0.");
}
if (($migrations = $this->getMigrationHistory($step)) === array()) {
if (($migrations = $this->getMigrationHistory($limit)) === array()) {
echo "No migration has been done before.\n";
return;
}
@ -241,14 +263,14 @@ class MigrateController extends Controller
if ($this->confirm('Redo the above ' . ($n === 1 ? 'migration' : 'migrations') . "?")) {
foreach ($migrations as $migration) {
if ($this->migrateDown($migration) === false) {
echo "\nMigration failed. All later migrations are canceled.\n";
if (!$this->migrateDown($migration)) {
echo "\nMigration failed. The rest of the migrations are canceled.\n";
return;
}
}
foreach (array_reverse($migrations) as $migration) {
if ($this->migrateUp($migration) === false) {
echo "\nMigration failed. All later migrations are canceled.\n";
if (!$this->migrateUp($migration)) {
echo "\nMigration failed. The rest of the migrations migrations are canceled.\n";
return;
}
}
@ -256,26 +278,35 @@ class MigrateController extends Controller
}
}
public function actionTo($args)
/**
* Upgrades or downgrades till the specified version of migration.
*
* This command will first revert the specified migrations, and then apply
* them again. For example,
*
* ~~~
* yiic migrate/to 101129_185401 # using timestamp
* yiic migrate/to m101129_185401_create_user_table # using full name
* ~~~
*
* @param string $version the version name that the application should be migrated to.
* This can be either the timestamp or the full name of the migration.
* @throws Exception if the version argument is invalid
*/
public function actionTo($version)
{
if (isset($args[0])) {
$version = $args[0];
} else {
throw new Exception("Please specify which version to migrate to.");
}
$originalVersion = $version;
if (preg_match('/^m?(\d{6}_\d{6})(_.*?)?$/', $version, $matches)) {
$version = 'm' . $matches[1];
} else {
throw new Exception("The version option must be either a timestamp (e.g. 101129_185401)\nor the full name of a migration (e.g. m101129_185401_create_user_table).");
throw new Exception("The version argument must be either a timestamp (e.g. 101129_185401)\nor the full name of a migration (e.g. m101129_185401_create_user_table).");
}
// try migrate up
$migrations = $this->getNewMigrations();
foreach ($migrations as $i => $migration) {
if (strpos($migration, $version . '_') === 0) {
$this->actionUp(array($i + 1));
$this->actionUp($i + 1);
return;
}
}
@ -287,7 +318,7 @@ class MigrateController extends Controller
if ($i === 0) {
echo "Already at '$originalVersion'. Nothing needs to be done.\n";
} else {
$this->actionDown(array($i));
$this->actionDown($i);
}
return;
}
@ -296,33 +327,40 @@ class MigrateController extends Controller
throw new Exception("Unable to find the version '$originalVersion'.");
}
public function actionMark($args)
/**
* Modifies the migration history to the specified version.
*
* No actual migration will be performed.
*
* ~~~
* yiic migrate/mark 101129_185401 # using timestamp
* yiic migrate/mark m101129_185401_create_user_table # using full name
* ~~~
*
* @param string $version the version at which the migration history should be marked.
* This can be either the timestamp or the full name of the migration.
* @throws Exception if the version argument is invalid or the version cannot be found.
*/
public function actionMark($version)
{
if (isset($args[0])) {
$version = $args[0];
} else {
throw new Exception('Please specify which version to mark to.');
}
$originalVersion = $version;
if (preg_match('/^m?(\d{6}_\d{6})(_.*?)?$/', $version, $matches)) {
$version = 'm' . $matches[1];
} else {
throw new Exception("Error: The version option must be either a timestamp (e.g. 101129_185401)\nor the full name of a migration (e.g. m101129_185401_create_user_table).");
throw new Exception("The version argument must be either a timestamp (e.g. 101129_185401)\nor the full name of a migration (e.g. m101129_185401_create_user_table).");
}
$db = $this->getDb();
// try mark up
$migrations = $this->getNewMigrations();
foreach ($migrations as $i => $migration) {
if (strpos($migration, $version . '_') === 0) {
if ($this->confirm("Set migration history at $originalVersion?")) {
$command = $db->createCommand();
$command = $this->db->createCommand();
for ($j = 0; $j <= $i; ++$j) {
$command->insert($this->migrationTable, array(
'version' => $migrations[$j],
'apply_time' => time(),
));
))->execute();
}
echo "The migration history is set at $originalVersion.\nNo actual migration was performed.\n";
}
@ -338,9 +376,11 @@ class MigrateController extends Controller
echo "Already at '$originalVersion'. Nothing needs to be done.\n";
} else {
if ($this->confirm("Set migration history at $originalVersion?")) {