generating-migrations.rst 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. Generating Migrations
  2. =====================
  3. Doctrine can generate blank migrations for you to modify or it can generate functional migrations for you by comparing
  4. the current state of your database schema to your mapping information.
  5. Generating Blank Migrations
  6. ---------------------------
  7. To generate a blank migration you can use the ``generate`` command:
  8. .. code-block:: sh
  9. $ ./vendor/bin/doctrine-migrations generate
  10. Diffing Using the ORM
  11. ---------------------
  12. If you are using the ORM, you can modify your mapping information and have Doctrine generate a migration
  13. for you by comparing the current state of your database schema to the mapping information that is defined by using
  14. the ORM. To test this functionality, create a new ``User`` entity located at ``lib/MyProject/Entities/User.php``.
  15. .. code-block:: php
  16. <?php
  17. namespace MyProject\Entities;
  18. /**
  19. * @Entity
  20. * @Table(name="users")
  21. */
  22. class User
  23. {
  24. /** @Id @Column(type="integer") @GeneratedValue */
  25. private $id;
  26. /** @Column(type="string", nullable=true) */
  27. private $username;
  28. public function setId(int $id)
  29. {
  30. $this->id = $id;
  31. }
  32. public function getId() : ?int
  33. {
  34. return $this->id;
  35. }
  36. public function setUsername(string $username) : void
  37. {
  38. $this->username = $username;
  39. }
  40. public function getUsername() : ?string
  41. {
  42. return $this->username;
  43. }
  44. }
  45. Now when you run the ``diff`` command it will generate a migration which will create the ``users`` table:
  46. .. code-block:: sh
  47. $ ./vendor/bin/doctrine-migrations diff
  48. Generated new migration class to "/data/doctrine/migrations-docs-example/lib/MyProject/Migrations/Version20180601215504.php"
  49. To run just this migration for testing purposes, you can use migrations:execute --up 'MyProject\Migrations\Version20180601215504'
  50. To revert the migration you can use migrations:execute --down 'MyProject\Migrations\Version20180601215504'
  51. Take a look at the generated migration:
  52. .. note::
  53. Notice how the table named ``example_table`` that we created earlier in the :ref:`Managing Migrations <managing-migrations>`
  54. chapter is being dropped. This is because the table is not mapped anywhere in the Doctrine ORM and the ``diff`` command
  55. detects that and generates the SQL to drop the table. If you want to ignore some tables in your database take a
  56. look at `Ignoring Custom Tables <#ignoring-custom-tables>`_ chapter.
  57. .. code-block:: php
  58. <?php
  59. declare(strict_types=1);
  60. namespace MyProject\Migrations;
  61. use Doctrine\DBAL\Schema\Schema;
  62. use Doctrine\Migrations\AbstractMigration;
  63. /**
  64. * Auto-generated Migration: Please modify to your needs!
  65. */
  66. final class Version20180601215504 extends AbstractMigration
  67. {
  68. public function getDescription() : string
  69. {
  70. return '';
  71. }
  72. public function up(Schema $schema) : void
  73. {
  74. // this up() migration is auto-generated, please modify it to your needs
  75. $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
  76. $this->addSql('CREATE TABLE users (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
  77. $this->addSql('DROP TABLE example_table');
  78. }
  79. public function down(Schema $schema) : void
  80. {
  81. // this down() migration is auto-generated, please modify it to your needs
  82. $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
  83. $this->addSql('CREATE TABLE example_table (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) DEFAULT NULL COLLATE latin1_swedish_ci, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
  84. $this->addSql('DROP TABLE users');
  85. }
  86. }
  87. Now you are ready to execute your diff migration:
  88. .. code-block:: sh
  89. $ ./vendor/bin/doctrine-migrations migrate
  90. My Project Migrations
  91. WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)y
  92. Migrating up to MyProject\Migrations\Version20180601215504 from MyProject\Migrations\Version20180601193057
  93. ++ migrating MyProject\Migrations\Version20180601215504
  94. -> CREATE TABLE users (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
  95. -> DROP TABLE example_table
  96. ++ migrated (took 75.9ms, used 8M memory)
  97. ------------------------
  98. ++ finished in 84.3ms
  99. ++ used 8M memory
  100. ++ 1 migrations executed
  101. ++ 1 sql queries
  102. The SQL generated here is the exact same SQL that would be executed if you were using the ``orm:schema-tool`` command.
  103. This just allows you to capture that SQL and maybe tweak it or add to it and trigger the deployment later across
  104. multiple database servers.
  105. Diffing Without the ORM
  106. -----------------------
  107. Internally the diff command generates a ``Doctrine\DBAL\Schema\Schema`` object from your entities metadata using an
  108. implementation of ``Doctrine\Migrations\Provider\SchemaProviderInterface``. To use the Schema representation
  109. directly, without the ORM, you must implement this interface yourself.
  110. The ``SchemaProviderInterface`` only has one method named ``createSchema``. This should return a ``Doctrine\DBAL\Schema\Schema``
  111. instance that represents the state to which you'd like to migrate your database.
  112. .. code-block:: php
  113. <?php
  114. use Doctrine\DBAL\Schema\Schema;
  115. use Doctrine\Migrations\Provider\SchemaProviderInterface;
  116. final class CustomSchemaProvider implements SchemaProviderInterface
  117. {
  118. public function createSchema()
  119. {
  120. $schema = new Schema();
  121. $table = $schema->createTable('users');
  122. $table->addColumn('id', 'integer', [
  123. 'autoincrement' => true,
  124. ]);
  125. $table->addColumn('username', 'string', [
  126. 'notnull' => false,
  127. ]);
  128. $table->setPrimaryKey(array('id'));
  129. return $schema;
  130. }
  131. }
  132. The ``StubSchemaProvider`` provided with the migrations library is another option.
  133. It simply takes a schema object to its constructor and returns it from ``createSchema``.
  134. .. code-block:: php
  135. <?php
  136. use Doctrine\DBAL\Schema\Schema;
  137. use Doctrine\Migrations\Provider\StubSchemaProvider;
  138. $schema = new Schema();
  139. $table = $schema->createTable('users');
  140. $table->addColumn('id', 'integer', [
  141. 'autoincrement' => true,
  142. ]);
  143. $table->addColumn('username', 'string', [
  144. 'notnull' => false,
  145. ]);
  146. $table->setPrimaryKey(array('id'));
  147. $provider = new StubSchemaProvider($schema);
  148. $provider->createSchema() === $schema; // true
  149. By default the Doctrine Migrations command line tool will only add the diff command if the ORM is present.
  150. Without the ORM, you'll have to add the diff command to your console application manually, passing in your schema
  151. provider implementation to the diff command's constructor. Take a look at the :ref:`Custom Integration <custom-integration>`
  152. chapter for information on how to setup a custom console application.
  153. .. code-block:: php
  154. <?php
  155. use Doctrine\Migrations\Tools\Console\Command\DiffCommand;
  156. $schemaProvider = new CustomSchemaProvider();
  157. /** @var Symfony\Component\Console\Application */
  158. $cli->add(new DiffCommand($schemaProvider));
  159. // ...
  160. $cli->run();
  161. With the custom provider in place the ``diff`` command will compare the current database schema to the one provided by
  162. the ``SchemaProviderInterface`` implementation. If there is a mismatch, the differences will be included in the
  163. generated migration just like the ORM examples above.
  164. Formatted SQL
  165. -------------
  166. You can optionally pass the ``--formatted`` option if you want the dumped SQL to be formatted. This option uses
  167. the ``doctrine/sql-formatter`` package so you will need to install this package for it to work:
  168. .. code-block:: sh
  169. $ composer require doctrine/sql-formatter
  170. Ignoring Custom Tables
  171. ----------------------
  172. If you have custom tables which are not managed by Doctrine you will need to tell Doctrine to ignore these tables.
  173. Otherwise, everytime you run the ``diff`` command, Doctrine will try to drop those tables. You can configure Doctrine
  174. with a schema filter.
  175. .. code-block:: php
  176. $connection->getConfiguration()->setFilterSchemaAssetsExpression("~^(?!t_)~");
  177. With this expression all tables prefixed with t_ will ignored by the schema tool.
  178. If you use the DoctrineBundle with Symfony you can set the ``schema_filter`` option
  179. in your configuration. You can find more information in the documentation of the
  180. DoctrineMigrationsBundle.
  181. Merging Historical Migrations
  182. -----------------------------
  183. If you have many migrations, which were generated by successive runs of the ``diff`` command over time,
  184. and you would like to replace them with one single migration, you can
  185. delete (or archive) all your "historical" migration files and
  186. run the ``diff`` command with the ``--from-empty-schema`` option.
  187. It will generate a full migration as if your database was empty.
  188. You can then use the ``rollup`` command to synchronize the version table of your (already up-to-date) database.
  189. :ref:`Next Chapter: Custom Configuration <custom-configuration>`