| | 3 | |
|---|
| | 4 | A common problem in web development is how to make changes to your database as your models evolve. The migrations support in Doctrine take care of this problem. |
|---|
| | 5 | |
|---|
| | 6 | sfDoctrinePlugin implements some additional tasks for generating migration classes both from existing databases and models. You can also use Doctrine to generate your blank skeleton migration classes. |
|---|
| | 7 | |
|---|
| | 8 | **Available Migration Tasks** |
|---|
| | 9 | |
|---|
| | 10 | :generate-migration Generate migration class (doctrine-generate-migration) |
|---|
| | 11 | :generate-migrations-db Generate migration classes from existing database connections (doctrine-generate-migrations-db, doctrine-gen-migrations-from-db) |
|---|
| | 12 | :generate-migrations-models Generate migration classes from an existing set of models (doctrine-generate-migrations-models, doctrine-gen-migrations-from-models) |
|---|
| | 13 | :migrate Migrates database to current/specified version (doctrine-migrate) |
|---|
| | 14 | |
|---|
| | 15 | The examples in this chapter assume you're working with the following schema and data fixtures. We'll use this as the base of all the examples documented here. |
|---|
| | 16 | |
|---|
| | 17 | **project/config/doctrine/schema.yml** |
|---|
| | 18 | |
|---|
| | 19 | BlogPost: |
|---|
| | 20 | actAs: |
|---|
| | 21 | I18n: |
|---|
| | 22 | fields: [title, body] |
|---|
| | 23 | Timestampable: |
|---|
| | 24 | columns: |
|---|
| | 25 | author: string(255) |
|---|
| | 26 | title: string(255) |
|---|
| | 27 | body: clob |
|---|
| | 28 | relations: |
|---|
| | 29 | Tags: |
|---|
| | 30 | class: Tag |
|---|
| | 31 | refClass: BlogPostTag |
|---|
| | 32 | foreignAlias: BlogPosts |
|---|
| | 33 | Tag: |
|---|
| | 34 | columns: |
|---|
| | 35 | name: string(255) |
|---|
| | 36 | BlogPostTag: |
|---|
| | 37 | columns: |
|---|
| | 38 | blog_post_id: |
|---|
| | 39 | type: integer |
|---|
| | 40 | primary: true |
|---|
| | 41 | tag_id: |
|---|
| | 42 | type: integer |
|---|
| | 43 | primary: true |
|---|
| | 44 | |
|---|
| | 45 | **project/data/fixtures.yml** |
|---|
| | 46 | |
|---|
| | 47 | BlogPost: |
|---|
| | 48 | BlogPost_1: |
|---|
| | 49 | author: Jonathan H. Wage |
|---|
| | 50 | Translation: |
|---|
| | 51 | en: |
|---|
| | 52 | title: Test Blog Post |
|---|
| | 53 | body: This is the body of the test blog post |
|---|
| | 54 | Tags: [php, orm] |
|---|
| | 55 | Tag: |
|---|
| | 56 | php: |
|---|
| | 57 | name: PHP |
|---|
| | 58 | orm: |
|---|
| | 59 | name: ORM |
|---|
| | 60 | |
|---|
| | 61 | # Generating Migrations |
|---|
| | 62 | |
|---|
| | 63 | ## From Database |
|---|
| | 64 | |
|---|
| | 65 | If you have an existing database you can build a set of migration classes that will re-create your database by running the following command. |
|---|
| | 66 | |
|---|
| | 67 | $ ./symfony doctrine:generate-migrations-db frontend |
|---|
| | 68 | >> doctrine Generated migration classes successfully from database |
|---|
| | 69 | |
|---|
| | 70 | ## From Models |
|---|
| | 71 | |
|---|
| | 72 | If you have an existing set of models you can build a set of migration classes that will create your database by running the following command. |
|---|
| | 73 | |
|---|
| | 74 | $ ./symfony doctrine:generate-migrations-models frontend |
|---|
| | 75 | >> doctrine Generated migration classes successfully from models |
|---|
| | 76 | |
|---|
| | 77 | Now that you have a set of migration classes you can reset your database and run the migrate command to re-create the database. |
|---|
| | 78 | |
|---|
| | 79 | $ ./symfony doctrine:drop-db frontend && ./symfony doctrine:build-db frontend && ./symfony doctrine:migrate frontend && ./symfony doctrine:data-load frontend |
|---|
| | 80 | >> doctrine Are you sure you wish to drop your databases? (y/n) |
|---|
| | 81 | y |
|---|
| | 82 | >> doctrine Successfully dropped database f...ction "doctrine" named "dbname" |
|---|
| | 83 | >> doctrine Successfully created database f...ction "doctrine" named "dbname" |
|---|
| | 84 | >> doctrine migrated successfully to version #5 |
|---|
| | 85 | >> doctrine Data was successfully loaded |
|---|
| | 86 | |
|---|
| | 87 | ## Skeleton |
|---|
| | 88 | |
|---|
| | 89 | Now that your database is all created and migrated to the latest version you can generate new migration class skeletons to migrate your schema as your model evolves. Imagine you have a new column you're adding to the BlogPost model named `excerpt`. Below is the updated BlogPost schema which includes the new column. |
|---|
| | 90 | |
|---|
| | 91 | BlogPost: |
|---|
| | 92 | actAs: |
|---|
| | 93 | I18n: |
|---|
| | 94 | fields: [title, body] |
|---|
| | 95 | Timestampable: |
|---|
| | 96 | columns: |
|---|
| | 97 | author: string(255) |
|---|
| | 98 | title: string(255) |
|---|
| | 99 | body: clob |
|---|
| | 100 | excerpt: string(255) |
|---|
| | 101 | relations: |
|---|
| | 102 | Tags: |
|---|
| | 103 | class: Tag |
|---|
| | 104 | refClass: BlogPostTag |
|---|
| | 105 | foreignAlias: BlogPosts |
|---|
| | 106 | |
|---|
| | 107 | Now we need to generate the blank migration skeleton for adding the `excerpt` column to the database. Run the following command to generate the migration class. |
|---|
| | 108 | |
|---|
| | 109 | $ ./symfony doctrine:generate-migration frontend AddBlogPostExcerptColumn |
|---|
| | 110 | >> doctrine Generated migration class: AddB...ymfony12/lib/migration/doctrine |
|---|
| | 111 | |
|---|
| | 112 | Now in `project/lib/migration/doctrine` you will see a new file named `006_add_blog_post_excerpt_column.class.php` with the following code in it. |
|---|
| | 113 | |
|---|
| | 114 | [php] |
|---|
| | 115 | /** |
|---|
| | 116 | * This class has been auto-generated by the Doctrine ORM Framework |
|---|
| | 117 | */ |
|---|
| | 118 | class AddBlogPostExcerptColumn extends Doctrine_Migration |
|---|
| | 119 | { |
|---|
| | 120 | public function up() |
|---|
| | 121 | { |
|---|
| | 122 | |
|---|
| | 123 | } |
|---|
| | 124 | |
|---|
| | 125 | public function down() |
|---|
| | 126 | { |
|---|
| | 127 | |
|---|
| | 128 | } |
|---|
| | 129 | } |
|---|
| | 130 | |
|---|
| | 131 | Each migration consists of an up() method and a down() method. Inside the up() is where you do things like add columns, create tables, etc. and the down() simply negates anything done in the up(). Each class essentially represents a version of your database and the up() and down() methods allow you to walk backwards and forwards between versions of your database. |
|---|
| | 132 | |
|---|
| | 133 | Now lets write the code for our new migration class to add the `excerpt` column. |
|---|
| | 134 | |
|---|
| | 135 | [php] |
|---|
| | 136 | /** |
|---|
| | 137 | * This class has been auto-generated by the Doctrine ORM Framework |
|---|
| | 138 | */ |
|---|
| | 139 | class AddBlogPostExcerptColumn extends Doctrine_Migration |
|---|
| | 140 | { |
|---|
| | 141 | public function up() |
|---|
| | 142 | { |
|---|
| | 143 | $this->addColumn('blog_post', 'excerpt', 'string', array('length' => '255')); |
|---|
| | 144 | } |
|---|
| | 145 | |
|---|
| | 146 | public function down() |
|---|
| | 147 | { |
|---|
| | 148 | $this->removeColumn('blog_post', 'excerpt'); |
|---|
| | 149 | } |
|---|
| | 150 | } |
|---|
| | 151 | |
|---|
| | 152 | Now you can run the following command and it will upgrade your database to the latest version using the migration class we just wrote and the excerpt column will be added to the database. |
|---|
| | 153 | |
|---|
| | 154 | $ ./symfony doctrine:migrate frontend |
|---|
| | 155 | >> doctrine migrated successfully to version #6 |
|---|
| | 156 | |
|---|
| | 157 | >**TIP** |
|---|
| | 158 | >More can be read about migrations in the Doctrine Manual [here](http://www.doctrine-project.org/documentation/manual/1_0?chapter=migration). |
|---|