I want to integrate Doctrine ORM into my (non-Symfony) project. I already done this in another project and used the famous cli-config.php
into the project root directory.
But now, in my new project, I use the Symfony Console component and the Dependency Injection component (to reference services and commands, by tagging them).
1. I absolutely don't want to have a cli-config.php
in the project root. How the Sf Doctrine Bundle do this?
2. Also (but it is less important), I would like to have the Doctrine commands into my project CLI.
What would be the best way to do this? Create references to Doctrine commands into my services.yml
? Or create local "decorator commands" that call Doctrine commands via PHP?
Finally, after some googling and experiments, I found a complete solution.
Just read the doctrine.php in vendor/bin
. It is very easy to avoid the hardcoded config-cli.php
file.
In my case, I use a factory and this method hydrates the doctrine.em
service.
($config
is specific to my app, change values to use your own logic.)
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
public function createEntityManager()
{
$config = $this->get('config');
$metadataConfig = Setup::createAnnotationMetadataConfiguration(
[$config->meta('app_path') . '/Entity'],
$config->oc->doctrine->dev_mode
);
return EntityManager::create((array) $config->oc->doctrine->connection, $metadataConfig);
}
Somewere in your code, like in some bootstrap.php
, you probably declare your Symfony\Component\Console\Application
command line interface, that's how I do this (the foreach
simply adds commands defined in my services.yml
file):
$application = new Application('MyApp CLI', '0.0.1');
$services = $container->findTaggedServiceIds('oc.command');
foreach(array_keys($services) as $serviceId)
{
$application->add($container->get($serviceId));
}
$application->run();
Now, we simply ask Doctrine to inject its commands into our Application:
$application = new Application('MyApp CLI', '0.0.1');
$helperSet = ConsoleRunner::createHelperSet($container->get('doctrine.em'));
$application->setHelperSet($helperSet);
ConsoleRunner::addCommands($application);
$services = $container->findTaggedServiceIds('oc.command');
foreach(array_keys($services) as $serviceId)
{
$application->add($container->get($serviceId));
}
$application->run();
That's it! You can also only add a subset of the Doctrine commands by using arsfeld's answer on this GitHub issue.
You can create decorator commands that inherit Doctrine commands (this is useful to redefine the name of Doctrine commands, as Symfony Doctrine Bundle does, eg. orm:validate-schema
-> doctrine:schema:validate
).
To do this, remove the line ConsoleRunner::addCommands($application);
we added in step 2. For each command you want to redefine, you will need to create an register a new command in your app. This command will "extends
" the target Doctrine command and will override the configure()
method.
Here is an example with orm:validate-schema
:
<?php
namespace MyApp\Command\Doctrine;
use Doctrine\ORM\Tools\Console\Command\ValidateSchemaCommand;
class SchemaValidateCommand extends ValidateSchemaCommand
{
protected function configure()
{
parent::configure();
$this->setName('doctrine:schema:validate');
}
}
Some Doctrine commands have aliases that will pollute your command namespaces, like orm:generate-entities
and orm:generate:entities
.
To remove these aliases, in configure()
, add ->setAliases(array())
.
$this->setName('doctrine:generate:entities')->setAliases([]);
Congratulations, you just redone the Symfony Doctrine Bundle :p (jk)