From d4e3567ab9d67fa61985e613d8358096cd94c662 Mon Sep 17 00:00:00 2001 From: "Jonathan.Wage" Date: Thu, 20 Sep 2007 20:24:38 +0000 Subject: [PATCH] Changes to migration. --- lib/Doctrine/Migration.php | 154 ++++++++++-------- manual/new/docs/en/migration.txt | 39 ++--- models/MigrationTest.php | 8 + tests/MigrationTestCase.php | 62 +------ tests/migration_classes/001_add_table.php | 13 ++ tests/migration_classes/002_change_column.php | 13 ++ 6 files changed, 147 insertions(+), 142 deletions(-) create mode 100644 models/MigrationTest.php create mode 100644 tests/migration_classes/001_add_table.php create mode 100644 tests/migration_classes/002_change_column.php diff --git a/lib/Doctrine/Migration.php b/lib/Doctrine/Migration.php index 0360a15cd..aed8f9345 100644 --- a/lib/Doctrine/Migration.php +++ b/lib/Doctrine/Migration.php @@ -43,7 +43,72 @@ class Doctrine_Migration 'added_indexes' => array(), 'removed_indexes' => array()); - static public function setCurrentVersion($number) + public $migrationTableName = 'migration_version'; + public $migrationClassesDirectory = array(); + public $migrationClasses = array(); + + public function __construct($directory = null) + { + if ($directory != null) { + $this->migrationClassesDirectory = $directory; + + $this->loadMigrationClasses(); + } + } + + protected function loadMigrationClasses() + { + $directory = $this->migrationClassesDirectory; + + $classes = get_declared_classes(); + + if ($directory !== null) { + foreach ((array) $directory as $dir) { + $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), + RecursiveIteratorIterator::LEAVES_ONLY); + + foreach ($it as $file) { + $e = explode('.', $file->getFileName()); + if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) { + require_once $file->getPathName(); + $requiredClass = array_diff(get_declared_classes(), $classes); + $requiredClass = end($requiredClass); + + $loadedClasses[$requiredClass] = $file->getFileName(); + + } + } + } + } + + $classes = $loadedClasses; + $parent = new ReflectionClass('Doctrine_Migration'); + $loadedClasses = array(); + + foreach ($classes as $name => $fileName) { + $class = new ReflectionClass($name); + + while ($class->isSubclassOf($parent)) { + + $class = $class->getParentClass(); + if ($class === false) { + break; + } + } + + if ($class === false) { + continue; + } + + $loadedClasses[$name] = $fileName; + } + + $this->migrationClasses = $loadedClasses; + + return $loadedClasses; + } + + public function setCurrentVersion($number) { $conn = Doctrine_Manager::connection(); @@ -62,7 +127,7 @@ class Doctrine_Migration } } - static public function getCurrentVersion() + public function getCurrentVersion() { $conn = Doctrine_Manager::connection(); @@ -71,93 +136,50 @@ class Doctrine_Migration return isset($result[0]) ? $result[0]:false; } - static public function migration($from, $to) + public function migrate($from, $to) { - if ($from === $to || $from === 0) { - throw new Doctrine_Migration_Exception('You specified an invalid migration path. The from and to cannot be the same and from cannot be zero.'); + if ($from === $to) { + throw new Doctrine_Migration_Exception('You specified an invalid migration path. The from and to cannot be the same.'); } $direction = $from > $to ? 'down':'up'; if ($direction === 'up') { for ($i = $from + 1; $i <= $to; $i++) { - self::doDirectionStep($direction, $i); + $this->doMigrateStep($direction, $i); } } else { for ($i = $from; $i > $to; $i--) { - self::doDirectionStep($direction, $i); + $this->doMigrateStep($direction, $i); } } - self::setCurrentVersion($to); + $this->setCurrentVersion($to); } - public static function doDirectionStep($direction, $num) + protected function getMigrationClass($num) { - $className = 'Migration' . $num; + $classes = $this->migrationClasses; - if (class_exists($className)) { - $migrate = new $className(); - $migrate->migrate($direction); - } else { - throw new Doctrine_Migration_Exception('Could not find migration class: ' . $className); + foreach ($classes as $className => $fileName) { + $e = explode('_', $fileName); + $classMigrationNum = (int) $e[0]; + + if ($classMigrationNum === $num) { + return new $className(); + } } + + throw new Doctrine_Migration_Exception('Could not find migration class for migration step: '.$num); } - public static function loadMigrationClasses($directory) + public function doMigrateStep($direction, $num) { - $classes = get_declared_classes(); - - if ($directory !== null) { - foreach ((array) $directory as $dir) { - $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), - RecursiveIteratorIterator::LEAVES_ONLY); - - foreach ($it as $file) { - $e = explode('.', $file->getFileName()); - if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) { - require_once $file->getPathName(); - } - } - } - - $classes = array_diff(get_declared_classes(), $classes); - } - - return self::getLoadedMigrationClasses($classes); + $migrate = $this->getMigrationClass($num); + $migrate->doMigrate($direction); } - public static function getLoadedMigrationClasses($classes = null) - { - if ($classes === null) { - $classes = get_declared_classes(); - } - - $parent = new ReflectionClass('Doctrine_Migration'); - $loadedClasses = array(); - - foreach ($classes as $name) { - $class = new ReflectionClass($name); - - while ($class->isSubclassOf($parent)) { - - $class = $class->getParentClass(); - if ($class === false) { - break; - } - } - - if ($class === false) { - continue; - } - - $loadedClasses[] = $name; - } - - return $loadedClasses; - } - - public function migrate($direction) + public function doMigrate($direction) { if (method_exists($this, $direction)) { $this->$direction(); diff --git a/manual/new/docs/en/migration.txt b/manual/new/docs/en/migration.txt index 6a317278a..5e5f3b714 100644 --- a/manual/new/docs/en/migration.txt +++ b/manual/new/docs/en/migration.txt @@ -2,18 +2,11 @@ The Doctrine Migration tools allow you to migrate databases and it issues alter ++ Writing Migration Classes -Migration classes consist of a simple class that extends from Doctrine_Migration. You can define a public up() and down() method that is meant for doing and undoing changes to a database for that migration step. +Migration classes consist of a simple class that extends from Doctrine_Migration. You can define a public up() and down() method that is meant for doing and undoing changes to a database for that migration step. The class name is completely arbitrary, but the name of the file which contains the class must have a prefix containing the number it represents in the migration process. Example: XXX_representative_name.class.php -class MigrationTest extends Doctrine_Record -{ - public function setTableDefinition() - { - $this->hasColumn('field1', 'string'); - } -} - -class Migration2 extends Doctrine_Migration +// 001_add_table.class.php +class AddTable extends Doctrine_Migration { public function up() { @@ -26,7 +19,8 @@ class Migration2 extends Doctrine_Migration } } -class Migration3 extends Doctrine_Migration +// 002_add_column.class.php +class AddColumn extends Doctrine_Migration { public function up() { @@ -39,7 +33,8 @@ class Migration3 extends Doctrine_Migration } } -class Migration4 extends Doctrine_Migration +// 003_change_column.class.php +class ChangeColumn extends Doctrine_Migration { public function up() { @@ -74,7 +69,8 @@ public function removeIndex($tableName, $indexName) You can alter table directly in your up() and down() methods like you normally would by creating new model instances and calling save() or creating queries and deleting data. -class Migration1 extends Doctrine_Migration +// XXX_add_user.class.php +class AddUser extends Doctrine_Migration { public function up() { @@ -97,16 +93,15 @@ class Migration1 extends Doctrine_Migration ++ Performing Migrations -// Upgrade one at a time -Doctrine_Migration::migration(1, 2); -Doctrine_Migration::migration(2, 3); -Doctrine_Migration::migration(3, 4); +$migration = new Doctrine_Migration('migration_classes'); +$migration->migrate(0, 1); +$migration->migrate(1, 2); +$migration->migrate(2, 3); // Then revert back to version 1 -Doctrine_Migration::migration(4, 1); +$migration->migrate(3, 2); +$migration->migrate(2, 1); +$migration->migrate(1, 0); -// One big upgrade -Doctrine_Migration::migration(1, 4); - -echo Doctrine_Migration::getCurrentVersion(); // should echo 4 +echo $migration->getCurrentVersion(); // should echo 0 \ No newline at end of file diff --git a/models/MigrationTest.php b/models/MigrationTest.php new file mode 100644 index 000000000..f042df011 --- /dev/null +++ b/models/MigrationTest.php @@ -0,0 +1,8 @@ +hasColumn('field1', 'string'); + } +} \ No newline at end of file diff --git a/tests/MigrationTestCase.php b/tests/MigrationTestCase.php index 3318a33c2..9e55aae26 100644 --- a/tests/MigrationTestCase.php +++ b/tests/MigrationTestCase.php @@ -33,63 +33,17 @@ class Doctrine_Migration_TestCase extends Doctrine_UnitTestCase { public function testMigration() - { + { // Upgrade one at a time - Doctrine_Migration::migration(1, 2); - Doctrine_Migration::migration(2, 3); - Doctrine_Migration::migration(3, 4); + $migration = new Doctrine_Migration('migration_classes'); + $migration->migrate(0, 1); + $migration->migrate(1, 2); // Then revert back to version 1 - Doctrine_Migration::migration(4, 1); + $migration->migrate(2, 1); + $migration->migrate(1, 0); - // Check to make sure the current version is 1 - $this->assertEqual(Doctrine_Migration::getCurrentVersion(), 1); + // Check to make sure the current version is 0 + $this->assertEqual($migration->getCurrentVersion(), 0); } -} - -class MigrationTest extends Doctrine_Record -{ - public function setTableDefinition() - { - $this->hasColumn('field1', 'string'); - } -} - -class Migration2 extends Doctrine_Migration -{ - public function up() - { - $this->createTable('migration_test', array('field1' => array('type' => 'string'))); - } - - public function down() - { - $this->dropTable('migration_test'); - } -} - -class Migration3 extends Doctrine_Migration -{ - public function up() - { - $this->addColumn('migration_test', 'field1', 'string'); - } - - public function down() - { - $this->renameColumn('migration_test', 'field1', 'field2'); - } -} - -class Migration4 extends Doctrine_Migration -{ - public function up() - { - $this->changeColumn('migration_test', 'field1', 'integer'); - } - - public function down() - { - $this->changeColumn('migration_test', 'field1', 'string'); - } } \ No newline at end of file diff --git a/tests/migration_classes/001_add_table.php b/tests/migration_classes/001_add_table.php new file mode 100644 index 000000000..c13464e84 --- /dev/null +++ b/tests/migration_classes/001_add_table.php @@ -0,0 +1,13 @@ +createTable('migration_test', array('field1' => array('type' => 'string'))); + } + + public function down() + { + $this->dropTable('migration_test'); + } +} \ No newline at end of file diff --git a/tests/migration_classes/002_change_column.php b/tests/migration_classes/002_change_column.php new file mode 100644 index 000000000..6da83391b --- /dev/null +++ b/tests/migration_classes/002_change_column.php @@ -0,0 +1,13 @@ +changeColumn('migration_test', 'field1', 'integer'); + } + + public function down() + { + $this->changeColumn('migration_test', 'field1', 'string'); + } +} \ No newline at end of file