Symfony 2: access updated configuration from within a command

We create a team that relies on other teams to create a new database and build its schema. So far, we have managed to read the config.yml file, add new connection information and write the file back. In the same command, we then try to run symfony commands to create the database and schema: update. Here we run into problems. We get the following error:

[InvalidArgumentException] Doctrine ORM Manager with the name "mynewdatabase" does not exist.

If we run the command a second time, there is no error, because the updated configuration file is loaded into the application new. If we manually run the doctrine commands after writing to the config.yml file, it also works without errors.

We think that at the time of our team, where we run the create and update database commands, it still uses the current kernel version config.yml / database.yml, which are stored in memory. We tried several ways to reinitialize the application / kernel configuration (shutdown shutdown (), boot (), etc.) without luck. Here is the code:

namespace Test\MyBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Yaml;

class GeneratorCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
           ->setName('generate')
           ->setDescription('Create a new database.')
           ->addArgument('dbname', InputArgument::REQUIRED, 'The db name')
        ;
    }

   /*
      example: php app/console generate mynewdatabase
   */
   protected function execute(InputInterface $input, OutputInterface $output)
   {
      //Without this, the doctrine commands will prematurely end execution
      $this->getApplication()->setAutoExit(false);

      //Open up app/config/config.yml
      $yaml = Yaml::parse(file_get_contents($this->getContainer()->get('kernel')->getRootDir() .'/config/config.yml'));

      //Take input dbname and use it to name the database
      $db_name = $input->getArgument('dbname');

      //Add that connection to app/config/config.yml
      $yaml['doctrine']['dbal']['connections'][$site_name] = Array('driver' => '%database_driver%', 'host' => '%database_host%', 'port' => '%database_port%', 'dbname' => $site_name, 'user' => '%database_user%', 'password' => '%database_password%', 'charset' => 'UTF8');
      $yaml['doctrine']['orm']['entity_managers'][$site_name] = Array('connection' => $site_name, 'mappings' => Array('MyCustomerBundle' => null));

      //Now put it back
      $new_yaml = Yaml::dump($yaml, 5);
      file_put_contents($this->getContainer()->get('kernel')->getRootDir() .'/config/config.yml', $new_yaml);

      /* http://symfony.com/doc/current/components/console/introduction.html#calling-an-existing-command */

      //Set up our db create script arguments
      $args = array(
         'command'      => 'doctrine:database:create',
         '--connection'   => $site_name,
      );
      $db_create_input = new ArrayInput($args);

      //Run the symfony database create arguments
      $this->getApplication()->run($db_create_input, $output);

      //Set up our schema update script arguments
      $args = array(
         'command'   => 'doctrine:schema:update',
         '--em'      => $site_name,
         '--force'   => true
      );
      $update_schema_input = new ArrayInput($args);

      //Run the symfony database create command
      $this->getApplication()->run($update_schema_input, $output);
   }
}
+5
source share
1 answer

The reason this does not work is because the DIC goes through the compilation process and then writes to a PHP file, which is then included in the current current process. What you can see here:

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Kernel.php#L562

"" ​​ , (require_once), DIC .

, , - Kernel, AppKernel. :

<?php

namespace Test\MyBundle\Command;

class FakeKernel extends \AppKernel
{
}

​​ , , DIC, "FakeKernel" , , . :

$kernel = new \Test\MyBundle\Command\FakeKernel($input->getOption('env'), true);
$application = new \Symfony\Bundle\FrameworkBundle\Console\Application($kernel);

, DIC:

$application->run($db_create_input, $output);

: . / .

+3

All Articles