Description
I've created a "PoC" project in order to ease with the bug reproduction, you can find it here: https://github.com/1ma/symfony-cmd-issue
Project contents
A brand new Symfony3 project with an empty entity (Test), its companion repository (TestRepository) and a command (TestCommand) defined as a service, as per the cookbook entry found at http://symfony.com/doc/current/cookbook/console/commands_as_services.html
# app/config/services.yml
services:
test_repo:
class: AppBundle\Repository\TestRepository
factory: ["@doctrine.orm.default_entity_manager", getRepository]
arguments: ["AppBundle:Test"]
test_command:
class: AppBundle\Command\TestCommand
arguments:
- "@test_repo"
tags:
- { name: console.command }
Steps to reproduce
-
$ git clone https://github.com/1ma/symfony-cmd-issue.git
-
$ cd symfony-cmd-issue; composer install
When the prompt shows up, be sure to set valid values for
database_user
anddatabase_password
. They should map to a MySQL user with enough permissions to create the database. -
At this point the installation will break. Further calls to
bin/console
will also fail with the following error message:marcel@workstation:~/workspace/symfony-cmd-issue$ php bin/console [Doctrine\DBAL\Exception\ConnectionException] An exception occured in driver: SQLSTATE[42000] [1049] Unknown database 'symfony' [Doctrine\DBAL\Driver\PDOException] SQLSTATE[42000] [1049] Unknown database 'symfony' [PDOException] SQLSTATE[42000] [1049] Unknown database 'symfony'
-
In order to restore the console, remove the
tags:
block from the command service definition. Now you'll be able to execute the console and create the database:marcel@workstation:~/workspace/symfony-cmd-issue$ php bin/console doctrine:database:create Created database `symfony` for connection named default
-
Once the database is created you can restore the
tags:
block in the command service definition and the console will still work:marcel@workstation:~/workspace/symfony-cmd-issue$ php bin/console cmd:test AppBundle\Entity\Test
-
Drop the database, and the console breaks again:
marcel@workstation:~/workspace/symfony-cmd-issue$ php bin/console doctrine:database:drop --force Dropped database for connection named `symfony` marcel@workstation:~/workspace/symfony-cmd-issue$ php bin/console cmd:test [Doctrine\DBAL\Exception\ConnectionException] An exception occured in driver: SQLSTATE[42000] [1049] Unknown database 'symfony' [Doctrine\DBAL\Driver\PDOException] SQLSTATE[42000] [1049] Unknown database 'symfony' [PDOException] SQLSTATE[42000] [1049] Unknown database 'symfony'
Troubleshooting
From what I've seen from the above exception stack trace, it seems that every service tagged with the console.command
tag is instantiated at Application::registerCommands()
.
Then, if one of the command dependencies is a subclass of EntityRepository
instantiated as EntityManager->getRepository('AppBundle:EntityName')
a connection to the database will be always attempted down the line, even if it doesn't exist yet.
Here is the full stack trace with some of the most relevant entries highlighted in bold font:
#0 .../symfony-cmd-issue/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php(45): Doctrine\DBAL\Driver\PDOConnection::__construct('mysql:host=127....', 'root', 'root', Array)
#1 .../symfony-cmd-issue/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(360): Doctrine\DBAL\Driver\PDOMySql\Driver->connect(Array, 'root', 'root', Array)
#2 .../symfony-cmd-issue/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(429): Doctrine\DBAL\Connection->connect()
#3 .../symfony-cmd-issue/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(389): Doctrine\DBAL\Connection->getDatabasePlatformVersion()
#4 .../symfony-cmd-issue/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(328): Doctrine\DBAL\Connection->detectDatabasePlatform()
#5 .../symfony-cmd-issue/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php(763): Doctrine\DBAL\Connection->getDatabasePlatform()
#6 .../symfony-cmd-issue/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php(616): Doctrine\ORM\Mapping\ClassMetadataFactory->getTargetPlatform()
#7 .../symfony-cmd-issue/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php(174): Doctrine\ORM\Mapping\ClassMetadataFactory->completeIdGeneratorMapping(Object(Doctrine\ORM\Mapping\ClassMetadata))
#8 .../symfony-cmd-issue/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(332): Doctrine\ORM\Mapping\ClassMetadataFactory->doLoadMetadata(Object(Doctrine\ORM\Mapping\ClassMetadata), NULL, false, Array)
#9 .../symfony-cmd-issue/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php(78): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->loadMetadata('AppBundle\Entit...')
#10 .../symfony-cmd-issue/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(216): Doctrine\ORM\Mapping\ClassMetadataFactory->loadMetadata('AppBundle\Entit...')
#11 .../symfony-cmd-issue/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php(281): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getMetadataFor('AppBundle:Test')
#12 .../symfony-cmd-issue/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php(44): Doctrine\ORM\EntityManager->getClassMetadata('AppBundle:Test')
#13 .../symfony-cmd-issue/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php(698): Doctrine\ORM\Repository\DefaultRepositoryFactory->getRepository(Object(Doctrine\ORM\EntityManager), 'AppBundle:Test')
#14 .../symfony-cmd-issue/var/cache/dev/appDevDebugProjectContainer.php(2465): Doctrine\ORM\EntityManager->getRepository('AppBundle:Test')
#15 .../symfony-cmd-issue/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php(273): appDevDebugProjectContainer->getTestRepoService()
#16 .../symfony-cmd-issue/var/cache/dev/appDevDebugProjectContainer.php(2452): Symfony\Component\DependencyInjection\Container->get('test_repo')
#17 .../symfony-cmd-issue/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php(273): appDevDebugProjectContainer->getTestCommandService()
#18 .../symfony-cmd-issue/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(101): Symfony\Component\DependencyInjection\Container->get('test_command')
#19 .../symfony-cmd-issue/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php(71): Symfony\Bundle\FrameworkBundle\Console\Application->registerCommands()
#20 .../symfony-cmd-issue/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php(117): Symfony\Bundle\FrameworkBundle\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#21 .../symfony-cmd-issue/bin/console(29): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput))
#22 {main}
Further details
Tested on a Debian Jessie x64 virtual machine with PHP 5.6, Symfony 3.0.2 and Doctrine ORM 2.5.4