Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Database Migrations

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Google for DoctrineMigrationsBundle. To install it, copy the composer require line. But again, we don't need to have the version - Composer will find the best version for us:

Tip

If you are on Symfony 3.2 or higher, you don't have to specify the bundle's version

composer require doctrine/doctrine-migrations-bundle:1.1

While Jordi is preparing that for us, let's keep busy. Copy the new statement from the docs and paste that into the AppKernel class:

... lines 1 - 5
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
... lines 11 - 20
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
... lines 22 - 23
);
... lines 25 - 33
}
... lines 35 - 54
}

Beautiful!

We already know that the main job of a bundle is to give us new services. But this bundle primarily gives us something different: a new set of console commands. Run bin/console with no arguments:

./bin/console

Hiding in the middle is a whole group starting with doctrine:migrations. These are our new best friend.

The Migrations Workflow

Our goal is to find a way to safely update our database schema both locally and on production.

To do this right, drop the database entirely to remove all the tables: like we have a new project.

./bin/console doctrine:database:drop --force

This is the only time you'll need to do this. Now, re-create the database:

./bin/console doctrine:database:create

Now, instead of running doctrine:schema:update, run:

./bin/console doctrine:migrations:diff

This created a new file in app/DoctrineMigrations. Go open that up:

... lines 1 - 10
class Version20160207083131 extends AbstractMigration
{
public function up(Schema $schema)
{
// this up() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("CREATE TABLE genus (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, sub_family VARCHAR(255) NOT NULL, species_count INT NOT NULL, fun_fact VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB");
}
public function down(Schema $schema)
{
// this down() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("DROP TABLE genus");
}
}

Check this out: the up() method executes the exact SQL that we would have gotten from the doctrine:schema:update command. But instead of running it, it saves it into this file. This is our chance to look at it and make sure it's perfect.

When you're ready, run the migration with:

./bin/console doctrine:migrations:migrate

Done! Obviously, when you deploy, you'll also run this command. But here's the really cool part: this command will only run the migration files that have not been executed before. Behind the scenes, this bundle creates a migrations_versions table that keep strack of which migration files it has already executed. This means you can safely run doctrine:migrations:migrate on every deploy: the bundle will take care of only running the new files.

Tip

You can run migration in reverse in case something fails. Personally, I never do this and I never worry about down() being correct. If you have a migration failure, it's a bad thing and it's better to diagnose and fix it manually.

Making Columns nullable

In newAction(), I'll add some code that sets fake data on the subFamily and speciesCount properties. But, I'll keep funFact blank: maybe some genuses just aren't very fun:

... lines 1 - 11
class GenusController extends Controller
{
... lines 14 - 16
public function newAction()
{
$genus = new Genus();
$genus->setName('Octopus'.rand(1, 100));
$genus->setSubFamily('Octopodinae');
$genus->setSpeciesCount(rand(100, 99999));
... lines 23 - 28
}
... lines 30 - 74
}

Ok, head over to /genus/new to try it out! Woh, a huge explosion!

Integrity constraint violation: 1048 Column fun_fact cannot be null

Here's the deal: Doctrine configures all columns to be required in the database by default. If you do want a column to be "nullable", find the column and add nullable=true:

... lines 1 - 10
class Genus
{
... lines 13 - 34
/**
* @ORM\Column(type="string", nullable=true)
*/
private $funFact;
... lines 39 - 79
}

Creating Another Migration

Of course, just because we made this change doesn't mean that our table was automatically updated behind the scenes. Nope: we need another migration. No problem! Go back to the terminal and run:

./bin/console doctrine:migrations:diff

Open up the new migration file: ALTER TABLE genus CHANGE fun_fact to have a default of null. This look perfect. Run it with:

./bin/console doctrine:migrations:migrate

So easy! Refresh the page again: no errors. Migrations are awesome.

Leave a comment!

80
Login or Register to join the conversation
Default user avatar
Default user avatar Hikaru Shindo | posted 4 years ago

Is it possible to save migrations to the bundles they belong to in case you may have more then one bundle with entities and do not want to recreate the migrations on each project?

45 Reply

Hi Hikaru!

As far as I know, that's not possible: but it's by design. Since there is only *one* database, it's better to install a bundle then just run 'doctrine:migrations:diff' to generate whatever migrations you need from that bundle. I think the authors of DoctrineMigrationsBundle were just worried about installing a bundle, running doctrine:migrations:migrate and suddenly something has altered your production database - maybe without you realizing :).

Cheers!

Reply
Default user avatar
Default user avatar Andy @ melt | posted 4 years ago

You mention in the video to not bother with the version info on the composer command for the doctrine-migration-bundle, but the installation failed for me without it. When I used the entire command given at on the instruction page (composer require doctrine/doctrine-migrations-bundle "^1.0") it worked flawlessly. Not sure if that will help anyone in a similar situation, but, FWIW... :)

4 Reply
Default user avatar
Default user avatar Lluís Puig Ferrer | Andy @ melt | posted 4 years ago

Same here! I just fixed adding the version in command too.

Reply

Yo Lluís Puig Ferrer!

Thanks for the comment! It looks like the newest version of this bundle isn't compat with the version of Symfony we were using in this tutorial (it would probably actually work just fine, but that bundle now requires a higher version). We're going to add a note to the video to help others :).

Cheers!

1 Reply
Default user avatar

I had an issue where it completely broke composer setup trying to get the package. Ended up deleting the `vendor` directory and running `composer clearcache` before updating my `composer.json` file with the values from the course code download.

"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.1.*",
"doctrine/orm": "^2.5",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"symfony/swiftmailer-bundle": "^2.3",
"symfony/monolog-bundle": "^2.8",
"sensio/distribution-bundle": "^5.0",
"sensio/framework-extra-bundle": "^3.0.2",
"incenteev/composer-parameter-handler": "^2.0",
"knplabs/knp-markdown-bundle": "^1.4",
"doctrine/doctrine-migrations-bundle": "^1.1"
}

Hope that helps!

Reply

Hey Neil Sweeney

Wow, what a strange issue. Could you explain me a bit more about what were you doing before all that happened? So I can help you finding the root cause of this problem

Cheers!

Reply

Hey Andy @ melt

Interesting situation... Could you tell me which error you had? and, thanks for sharing your solution!

Have a nice day :)

Reply
Default user avatar

Sorry to leave out the context... Error (without using the "^1.0" at the end of the composer command was (displayed in the termin on a red background): "Your requirements could not be resolved to an installable set of packages." Then composer dumped a bunch of info on things it didn't install, then it ended with another red line: "Installation failed, reverting ./composer.json to its original content."

Here's the entire composer output:

andy$ composer require doctrine/doctrine-migrations-bundle
Using version ^1.3 for doctrine/doctrine-migrations-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

Problem 1


- Conclusion: don't install symfony/symfony v3.1.4
- doctrine/doctrine-migrations-bundle v1.3.0 requires symfony/framework-bundle ~2.7|~3.3|~4.0 -> satisfiable by symfony/framework-bundle[v2.7.0, v2.7.1, v2.7.10, v2.7.11, v2.7.12, v2.7.13, v2.7.14, v2.7.15, v2.7.16, v2.7.17, v2.7.18, v2.7.19, v2.7.2, v2.7.20, v2.7.21, v2.7.22, v2.7.23, v2.7.24, v2.7.25, v2.7.26, v2.7.27, v2.7.28, v2.7.29, v2.7.3, v2.7.30, v2.7.31, v2.7.32, v2.7.33, v2.7.34, v2.7.35, v2.7.36, v2.7.4, v2.7.5, v2.7.6, v2.7.7, v2.7.8, v2.7.9, v2.8.0, v2.8.1, v2.8.10, v2.8.11, v2.8.12, v2.8.13, v2.8.14, v2.8.15, v2.8.16, v2.8.17, v2.8.18, v2.8.19, v2.8.2, v2.8.20, v2.8.21, v2.8.22, v2.8.23, v2.8.24, v2.8.25, v2.8.26, v2.8.27, v2.8.28, v2.8.29, v2.8.3, v2.8.4, v2.8.5, v2.8.6, v2.8.7, v2.8.8, v2.8.9, v3.3.0, v3.3.1, v3.3.10, v3.3.11, v3.3.2, v3.3.3, v3.3.4, v3.3.5, v3.3.6, v3.3.7, v3.3.8, v3.3.9].
- doctrine/doctrine-migrations-bundle v1.3.1 requires symfony/framework-bundle ~2.7|~3.3|~4.0 -> satisfiable by symfony/framework-bundle[v2.7.0, v2.7.1, v2.7.10, v2.7.11, v2.7.12, v2.7.13, v2.7.14, v2.7.15, v2.7.16, v2.7.17, v2.7.18, v2.7.19, v2.7.2, v2.7.20, v2.7.21, v2.7.22, v2.7.23, v2.7.24, v2.7.25, v2.7.26, v2.7.27, v2.7.28, v2.7.29, v2.7.3, v2.7.30, v2.7.31, v2.7.32, v2.7.33, v2.7.34, v2.7.35, v2.7.36, v2.7.4, v2.7.5, v2.7.6, v2.7.7, v2.7.8, v2.7.9, v2.8.0, v2.8.1, v2.8.10, v2.8.11, v2.8.12, v2.8.13, v2.8.14, v2.8.15, v2.8.16, v2.8.17, v2.8.18, v2.8.19, v2.8.2, v2.8.20, v2.8.21, v2.8.22, v2.8.23, v2.8.24, v2.8.25, v2.8.26, v2.8.27, v2.8.28, v2.8.29, v2.8.3, v2.8.4, v2.8.5, v2.8.6, v2.8.7, v2.8.8, v2.8.9, v3.3.0, v3.3.1, v3.3.10, v3.3.11, v3.3.2, v3.3.3, v3.3.4, v3.3.5, v3.3.6, v3.3.7, v3.3.8, v3.3.9].
- don't install symfony/framework-bundle v2.7.0|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.1|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.10|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.11|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.12|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.13|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.14|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.15|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.16|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.17|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.18|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.19|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.2|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.20|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.21|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.22|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.23|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.24|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.25|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.26|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.27|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.28|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.29|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.3|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.30|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.31|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.32|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.33|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.34|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.35|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.36|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.4|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.5|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.6|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.7|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.8|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.7.9|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.0|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.1|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.10|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.11|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.12|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.13|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.14|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.15|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.16|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.17|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.18|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.19|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.2|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.20|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.21|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.22|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.23|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.24|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.25|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.26|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.27|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.28|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.29|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.3|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.4|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.5|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.6|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.7|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.8|don't install symfony/symfony v3.1.4
- don't install symfony/framework-bundle v2.8.9|don't install symfony/symfony v3.1.4
- symfony/framework-bundle v3.3.0 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.1 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.10 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.11 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.2 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.3 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.4 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.5 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.6 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.7 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.8 conflicts with symfony/symfony[v3.1.4].
- symfony/framework-bundle v3.3.9 conflicts with symfony/symfony[v3.1.4].
- Installation request for symfony/symfony (locked at v3.1.4, required as 3.1.*) -> satisfiable by symfony/symfony[v3.1.4].
- Installation request for doctrine/doctrine-migrations-bundle ^1.3 -> satisfiable by doctrine/doctrine-migrations-bundle[v1.3.0, v1.3.1].

Installation failed, reverting ./composer.json to its original content.

Reply

Look's like you have an incompatibility between "symfony" and "symfony/framework-bundle" versions. Could you show me your composer.json file too? Let's find out what's going on here :)

Reply
Default user avatar

Hopefully this is the same project... I've been rifling through many tutorials and the directories are piling up!


{
"name": "knpuniversity/symfony",
"license": "proprietary",
"type": "project",
"autoload": {
"psr-4": {
"": "src/"
},
"classmap": [ "app/AppKernel.php", "app/AppCache.php" ]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.1.*",
"doctrine/orm": "^2.5",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"symfony/swiftmailer-bundle": "^2.3",
"symfony/monolog-bundle": "^2.8",
"symfony/polyfill-apcu": "^1.0",
"sensio/distribution-bundle": "^5.0",
"sensio/framework-extra-bundle": "^3.0.2",
"incenteev/composer-parameter-handler": "^2.0",
"knplabs/knp-markdown-bundle": "^1.4",
"doctrine/doctrine-migrations-bundle": "^1.0"
},
"require-dev": {
"sensio/generator-bundle": "^3.0",
"symfony/phpunit-bridge": "^3.0",
"doctrine/doctrine-fixtures-bundle": "^2.4",
"nelmio/alice": "2.1.4"
},
"scripts": {
"post-install-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
],
"post-update-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
]
},
"extra": {
"symfony-app-dir": "app",
"symfony-bin-dir": "bin",
"symfony-var-dir": "var",
"symfony-web-dir": "web",
"symfony-tests-dir": "tests",
"symfony-assets-install": "relative",
"incenteev-parameters": {
"file": "app/config/parameters.yml"
}
}
}
Reply

Hmm, ok, let's try this:
First, remove entirely your vendor's directory and the doctrine-migrations-bundle entry in your composer.json
Then, run `composer install` -> `composer update` -> `composer require doctrine/doctrine-migrations-bundle`

I believe it will do the trick ;)

Reply
Default user avatar

So, everything went swimmingly until I ran the 'composer update' command, which barfed this out onto the screen:


Updating the "app/config/parameters.yml" file
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::buildBootstrap
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache
PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineMigrationsBundle" from namespace "Doctrine\Bundle\MigrationsBundle".
Did you forget a "use" statement for another namespace? in /Users/andy/Projects/Symfony/symfony-doctrine/start/app/AppKernel.php:20
Stack trace:
#0 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(396): AppKernel->registerBundles()
#1 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(114): Symfony\Component\HttpKernel\Kernel->initializeBundles()
#2 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(68): Symfony\Component\HttpKernel\Kernel->boot()
#3 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(116): Symfony\Bundle\FrameworkBundle\Console\Application-> in /Users/andy/Projects/Symfony/symfony-doctrine/start/app/AppKernel.php on line 20

Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineMigrationsBundle" from namespace "Doctrine\Bundle\MigrationsBundle".
Did you forget a "use" statement for another namespace? in /Users/andy/Projects/Symfony/symfony-doctrine/start/app/AppKernel.php:20
Stack trace:
#0 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(396): AppKernel->registerBundles()
#1 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(114): Symfony\Component\HttpKernel\Kernel->initializeBundles()
#2 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(68): Symfony\Component\HttpKernel\Kernel->boot()
#3 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(116): Symfony\Bundle\FrameworkBundle\Console\Application-> in /Users/andy/Projects/Symfony/symfony-doctrine/start/app/AppKernel.php on line 20
Script Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache handling the post-update-cmd event terminated with an exception


[RuntimeException]
An error occurred when executing the "'cache:clear --no-warmup'" command:
Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineMigrationsBu
ndle" from namespace "Doctrine\Bundle\MigrationsBundle".
Did you forget a "use" statement for another namespace? in /Users/andy/Projects/Symfony/symfony-doctrine/start/app/AppKernel.
php:20
Stack trace:
#0 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(396
): AppKernel->registerBundles()
#1 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(114
): Symfony\Component\HttpKernel\Kernel->initializeBundles()
#2 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Appl
ication.php(68): Symfony\Component\HttpKernel\Kernel->boot()
#3 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(1
16): Symfony\Bundle\FrameworkBundle\Console\Application-> in /Users/andy/Projects/Symfony/symfony-doctrine/start/app/AppKerne
l.php on line 20
PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineMigrati
onsBundle" from namespace "Doctrine\Bundle\MigrationsBundle".
Did you forget a "use" statement for another namespace? in /Users/andy/Projects/Symfony/symfony-doctrine/start/app/AppKernel.
php:20
Stack trace:
#0 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(396
): AppKernel->registerBundles()
#1 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(114
): Symfony\Component\HttpKernel\Kernel->initializeBundles()
#2 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Appl
ication.php(68): Symfony\Component\HttpKernel\Kernel->boot()
#3 /Users/andy/Projects/Symfony/symfony-doctrine/start/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(1
16): Symfony\Bundle\FrameworkBundle\Console\Application-> in /Users/andy/Projects/Symfony/symfony-doctrine/start/app/AppKerne
l.php on line 20


update [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--lock] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no-progress] [--no-suggest] [--with-dependencies] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [-i|--interactive] [--root-reqs] [--] [<packages>]...
Reply

Hey Andy,
Actually, this is good - Composer upgrade your dependencies, but since you don't have DoctrineMigrationsBundle yet it's failed (I suppose you registered this bundle in AppKernel *before* you install it). So your next step - run "composer require doctrine/doctrine-migrations-bundle" and now Composer should be able to download this bundle and you won't see this error anymore (in theory). Let us know if something go wrong.

Cheers!

Reply

Using Doctrine's automatic database creation/update via annotations seems like an amazing feature
Are migrations used a lot in the Symfony world? Because at this point you might aswell use Laravel :p

Reply

Hey Leif__

You're correct, Doctrine migrations are great! and yes, they are a must when you decide to go to production, you should never update your DB schema by using doctrine:schema:update command

Cheers!

Reply

I actually like it after watching the video and using it

In Laravel I used to write my migrations by hand, I don't know if there is a package that can generate them from annotation. I really like the way it works here (Write your class with annotations, generate the migration)

Reply

You may find interesting this library then https://github.com/doctrine...

What I like to do is to auto-generate migrations by running bin/console doctrine:migration:diff
Usually I only create one migration per Pull Request. My way to go is first finish the PR without generating any migration files, but then, I checkout to master, reload the database schema and then checkout again into the PR's branch and finally run bin/console doctrine:migration:diff with all the new changes

Cheers!

Reply
Max S. Avatar

Hey!
Actually I don' really got the point why using migrations is so useful... Just for seeing the SQL code before you run it could be solved differently without a external file.
Furthermore you say that it just runs the newly generated migration files. But wouldn't do doctrine:schema:update do basically the same - applying only my NEW changes (as the old ones are already mirrored in the database) using the various ORM annotations to the database by looking at it, substracting the status quo from the entity-annotation-status and showing my the necessary changes in SQL language?

I got the feeling that the migrations create something like an version control system for the database schema as there's also the down function in the migration file. But is there a real-life scenario where you would use that - downgrading your database to a previous state?

As always: thanks in advance!

Reply

Hey Max,

Migrations allows you to automate updating DB in production safely (of course, you should double check all the new migrations to ensure that they contain safe instructions). The most common example I know is that you can rename entity's property, i.e. rename column in DB. But if you blindly run doctrine:schema:update - Doctrine will just add a new column and drop existent one, i.e. you will lose your data! Probably, It's not important for development - you can just reload your fixtures again, but it's very critical for production. And migrations solve this problem for you. I mean, doctrine:schema:update command isn't perfect, and sometimes you need to do some extra work. So if you write a good migration - you can safely execute it on production server without losing your data.

What about downgrading - it's a very rare cases. Btw, we don't care much about it on KnpU. If something went wrong - we manually execute some SQL commands to return DB in the previous state based on upgrading commands and using "doctrine:schema:update --dump-sql" for help. But probably in some projects using downgrading makes sense, especially if project under the active development and has a big team.

I hope it clearer for you now.

Cheers!

Reply
Max S. Avatar

Hey Victor!

Thank you very much for your reply. How exactly are migrations solving that problem? When I run doctrine:migrations:diff the SQL says (after adding a new property and changing an old one to a new name):

$this->addSql('ALTER TABLE yoda_event ADD test VARCHAR(255) NOT NULL, CHANGE details dummy LONGTEXT NOT NULL');

doctrine:schema:update --dump-sql creates the same statement:

ALTER TABLE yoda_event ADD test VARCHAR(255) NOT NULL, CHANGE details dummy LONGTEXT NOT NULL;

So besides of creating a history of my database changes, where is the difference of running a checked (via --dump-sql ) doctrine:schema:update and a migration checked via looking at the php?? A doctrine:migrations statement could be equally flawed as a doctrine:schema:update statement, so both could possibly "destroy" parts of my production database.

Reply

Yo Max!

Yea, amazingly, under many (but not all) situations, Doctrine DOES turn notice the renaming and turn it into a CHANGE query. That's pretty cool :). So, you're 100% right about doctrine:migrations:diff and doctrine:schema:update being equally perfect or equally flawed in the SQL they generate: if one somehow generates some SQL that isn't quite right, then they both will generate that (they generate the SQL using the same engine).

The big advantage of migrations is when you deploy your app to production *and* when you have those not-so-common cases where the generated SQL isn't perfect. Let me give you an example: suppose I'm adding a new column to Event, e.g. slug (URL-safe, unique string), and I give it unique=true. The generated SQL for that will look totally fine. But when I run it, it'll likely fail: if there are any Event objects already in the database, then they will all be given a blank slug... which of course isn't unique :). The fix, would be no:

A) NOT make the field unique, and generate a migration for just the new (non-unique field)
B) Add a second migration by hand (or update the first) that does some sort of a *data* migration - calculating and setting unique slug values on each row
C) Make the slug field unique again, and generate a migration for *just* the unique change

Now, if you deploy to production and run doctrine:migrations:migrate, that entire, validated & safe history is replayed. Obviously, that can't be done with doctrine:schema:update.

I know people that deployed and used doctrine:schema:update on production for a long time. It will work 99% of the time, but eventually it won't :). The big difference with migrations is that it actually allows you to *change* the SQL to fix whatever problem it has, and doctrine:schema:update doesn't give us that chance.

Cheers!

Reply
Max S. Avatar

Well, that sounds reasonable :) Thank you very much!

Reply
Default user avatar
Default user avatar Dan Costinel | posted 4 years ago

Hi Ryan,
Little question: did you ever had a situation when you wanted to deploy a Symfony app into a server which doesn't provide a way to run console commands? What was your approach in that case? Because you say that whenever we need to deploy we need to run doctrine:migrations:migrate too... And I need to deploy a Symfony app without being able to run console commands

Reply

Hey, Dan!

If you don't have access to the console command - change your hosting provider ;)

If seriously, you don't have many options here. You should run migration commands manually. You probably should have access to the PhpMyAdmin or credentials to connect to the database with MySQL Workbench. But in this case it's difficult to control it due to the human factor, you may miss something, which will cause an error. So the better option is to change your hosting provider.

Cheers!

Reply
Default user avatar
Default user avatar Dan Costinel | victor | posted 4 years ago

Still some months left for my current deal with the hosting company. And yeah, I'm taking into consideration to change the hosting provider. I thought there might be other solutions to my problem... Anyways, thanks for the tip.

Reply
Default user avatar
Default user avatar Д. Энхбаяр | posted 4 years ago

Hey

$ ./bin/console doctrine:migrations:migrate

Application Migrations

WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)n
Migration cancelled!

Databases only migration_versions create done Genus table not create symfony 3.2.1

Reply

Yo Д. Энхбаяр ,

You should type "y" (yes) instead of "n", i.e. you should agree with this warning. It's difficult to understand what is your question here. Could you explain it?

Cheers!

Reply
Default user avatar
Default user avatar Д. Энхбаяр | victor | posted 4 years ago

Sorry poor English language ..
"y" and "n" Results out of the same

Reply

OK, as I understand, when you run migrations - the Genus table will not created, right? Do you have any errors in the console? Actually, if you modify the migration *after* it was executed - it will be skipped the second time. So in this case you need to rollback it and then run migrations again:


$ bin/console doctrine:migration:execute 1234567890 --down
$ bin/console doctrine:migration:migrate


I hope it helps you.

Cheers!

Reply
Default user avatar

Hi Ryan,

I am trying to install the require doctrine/doctrine-migrations-bundle. However I keep getting this back : [Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException]

You have requested a non-existent parameter "database_path". Did you mean one of these: "database_host", "database_port", "database_name", "database_user"?

I've check my parameters.yml.dist and parameters.yml and neither have the key of database_path. Not really sure where the error is coming from.

Thanks

Reply

Hi Claire!

Ok, let's figure this out :). First, the error isn't coming exactly from running composer require. But instead, after compose require finishes running, Symfony does some final clean up (e.g. it clears its own cache). When *this* is happening, we're getting this error.

And at first, the reason is really simple: somewhere (probably config.yml) you are referencing %database_path%. But, this is *missing* from your parameters.yml file. It's very likely that you *did* have database_path in parameters.yml, until you ran composer require. You see, there is an extra process that runs whenever you run composer require/update/install. This process - called the "incenteev parameter handler" - compares your parameters.yml.dist file and your parameters.yml files. If you are missing something from your parameters.yml file (as compared to the .dist file) it will ask you for a value and fill it in for you. BUT, if you have some *extra* keys in parameters.yml (like database_path) that you forgot to add to your parameters.yml.dist file, it will actually remove them from parameters.yml! I've always disliked that feature, but I bet this is what's happening.

The fix:

- re-add database_path to your parameters.yml file
- also add database_path to parameters.yml.dist (it can be set to any value - it just needs to be there).

The next time you use Composer, it won't remove your database_host parameter. Btw, you can see where this "magic" parameters handler thing is registered - if you look at your composer.json file, under post-install-cmd/post-update-cmd section: https://github.com/symfony/....

Let me know if that fixes it! Cheers!

Reply
Default user avatar

Thankyou!!
It worked and thank you again for explaining what was happening when you run composer. Really interesting to find out about this feature 'incenteev parameter handler'.

Claire

Reply
Default user avatar
Default user avatar Peter Stephens | posted 4 years ago

Hey guys, When I try to run "php bin/console doctrine:migrations:migrate" I get,

Migrating up to 20160918154810 from 0
Migration 20160918154810 failed during Pre-Checks. Error Provided type "?Doctrine\DBAL\Schema\SchemaConfig" is invalid: must conform "/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*$/"

[Zend\Code\Generator\Exception\InvalidArgumentException]
Provided type "?Doctrine\DBAL\Schema\SchemaConfig" is invalid: must conform "/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*$/"

doctrine:migrations:migrate [--write-sql] [--dry-run] [--query-time] [--allow-no-migration] [--configuration [CONFIGURATION]] [--db-configuration [DB-CONFIGURATION]] [--db DB] [--em EM] [--shard SHARD] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-e|--env ENV] [--no-debug] [--] <command> [<version>]

I did find this, http://stackoverflow.com/qu...

However I don't really understand what the writer is implying.

Reply

Hey Peter!

Wow, I don't understand that either! And when I googled for it, I could *also* only find that same *one* like on the Internet about this :/. I'm not sure if it matters, but what version of PHP are you running?

I would try this one thing: delete your entire vendor/ directory and use composer to re-install. You should *not* need to do this... but this is a really strange error :).


rm -rf vendor/
composer install

Let me know if that works, or if there's anything else that may be non-traditional about your setup.

Cheers!

Reply
Default user avatar
Default user avatar Peter Stephens | weaverryan | posted 4 years ago

Thanks for tip, but no dice. I have PHP7.1 on Ubuntu. It probably has to do with that version as the other post states.

I did find the regex expression in the file, "vendor/zendframework/zend-code/src/Generator/TypeGenerator.php" and can see that it is from the "fromTypeString" function. I can also see that "fromTypeString" is getting called from "setType" in "vendor/zendframework/zend-code/src/Generator/ParameterGenerator.php". I kinda lose it from there.

Do you think the "question mark" at the beginning of the dump is an indicator or what it is actually complaining about? I went to "http://www.phpliveregex.com/" and used the "preg_match" to look at the regex and it matches "Doctrine\DBAL\Schema\SchemaConfig", but not "?Doctrine\DBAL\Schema\SchemaConfig".

- Pete

Reply

Hey Peter,

IIRC, it was a bug which fixed in the newest version of this library. What version of zendframework/zend-code do you use? Please, try to update zendframework/zend-code to the latest available version. I see the latest version is 3.0.4 now. You could try to update only this package with next command in console:


$ composer update zendframework/zend-code

Cheers!

Reply
Default user avatar
Default user avatar Peter Stephens | victor | posted 4 years ago

Oh cool! I will try that. Thanks Victor.

Reply
Default user avatar
Default user avatar Peter Stephens | victor | posted 4 years ago

Looks like I am already at 3.0.4

$ composer show -i | grep -i zend
You are using the deprecated option "installed". Only installed packages are shown by default now. The --all option can be used to show all packages.
zendframework/zend-code 3.0.4 provides facilities to generate arbitrary code using an object oriented interface
zendframework/zend-eventmanager 3.0.1 Trigger and listen to events within a PHP application

Reply

Hm, probably I was wrong about package, Could you try to update all your dependencies to the latest versions with: $ composer update?

Reply
Default user avatar

"composer upgrade" did upgrade a few packages, but did not fix the problem. I downgraded to PHP 7.0 and it works fine. I will stick with that as I have no real reason to use PHP 7.1. Thanks for the tips. I learned a lot.

- Pete

Reply

Hey Pete!

Over the weekend, I finally discovered the problem: a backwards-compatibility break in PHP 7.1. Some of the guys in charge of these very libraries that are involved are working to try to revert it before 7.1 is fully released.

Here's more info: https://github.com/php/php-.... And yes, there literally is a ? being added somewhere internally, and it's (at least in theory) by design.

Cheers!

Reply
Default user avatar
Default user avatar Shairyar Baig | posted 4 years ago

Hi Ryan, I am a bit confused.

I have two copies of the code, one sitting locally on my laptop and another a production copy which is uploaded via ftp sitting on a server. So if I run the command /bin/console doctrine:migrations:diff on my laptop this will create a migration file locally, do I then upload that file on the server and run the command /bin/console doctrine:migrations:migrate there?

Reply

Hey Shairyar!

Yep, that's exactly right! The Doctrine migrations library keeps a migration_versions table in your database (both locally and on production - basically inside any database where the app is run) that keeps track of what migrations were and were not run. So, the flow looks like this:

1) [Local] Make some entity changes
2) [Local] Run doctrine:migrations:diff to create the new file in app/DoctrineMigrations/
3) [Local] Run doctrine:migrations:migrate to execute that file locally and record that this migration file has been executed in the migration_versions table (of your local database).

... then eventually you copy ALL files, including the migration files to production. At this point, suppose that you have actually created *3* new migration files since you last deployed your files.

4) [Production] Run doctrine:migrations:migrate. This will look at the migration_versions table on your *production* database and notice that there are *3* new files in your app/DoctrineMigrations directory that have not been executed against that database yet. Then, it will execute those 3 migrations and record 3 new rose in the migration_versions table.

So, really, running doctrine:migrations:migrate should just be part of your deploy process - I usually do it right after copying my files and clearing cache.

Cheers!

Reply
Default user avatar
Default user avatar Shairyar Baig | weaverryan | posted 4 years ago

Many thanks Ryan, I tried this and it seems to work pretty well.

Reply
Default user avatar
Default user avatar jian su | posted 4 years ago

Good morning! just a question. If the production DB is not version control, I mean never ran any migration before. Now I decide to do it now. and run >php console doctrine:migrations:migrate. what would happen? Is it safe to do that? I really want to know. Thanks

Reply

Hey Jian,

It depends! Let's look at some example: you have locally and on production the same code with synced DB schema and everything works fine. Then you want to start using migrations. You did some schema-related changes locally (for example, add new column) and create a migration. Then this migration you can safely run on the production, but right after when the migration was created you have to validate queries in it - they should be safe. In my example you should have one single query, something like "ALTER TABLE table_name ADD column_name" and that's it. So obviously this query is safe enough on production.

But if you decide to start using migration and will remove locally all the tables inside the DB and try to add them with migrations - I think you see that this won't be safe to run on production ;)

Cheers!

Reply
Default user avatar

Thank you so much! it make total senses now!. so the take way here is Don't ever do remove tables on local and then uploads to production. Do it when it is adding columns!.

Reply

Hey Jian,

You can add "DELETE" queries to your migrations as well, but only when it's on purpose, i.e. you have to remove the table or column locally AND on production. The important is how do you start using migration. If you start using migrations from scratch of your project - I don't see any problems. But if you start using migrations on already existent project which already has production DB with real data - then you should start writing migrations locally on the same state which your production DB has ;)

Cheers!

Reply
Default user avatar
Default user avatar Darmanto Yang | posted 4 years ago

Hi,

I have problem when install the bundle.

Using version ^1.3 for doctrine/doctrine-migrations-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
> Incenteev\ParameterHandler\ScriptHandler::buildParameters
Updating the "app/config/parameters.yml" file
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::buildBootstrap
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache

// Clearing the cache for the dev environment with debug true

[OK] Cache for the "dev" environment (debug=true) was successfully cleared.

> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::installAssets

Trying to install assets as relative symbolic links.

[OK] No assets were provided by any bundle.

> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::installRequirementsFile
> Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::prepareDeploymentTarget

The composer was not show anything after this. i have wait for 1 hour.
Any suggestion?

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.4", // 1.4.2
        "doctrine/doctrine-migrations-bundle": "^1.1" // 1.1.1
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0", // v3.1.3
        "nelmio/alice": "^2.1", // 2.1.4
        "doctrine/doctrine-fixtures-bundle": "^2.3" // 2.3.0
    }
}