[DoctrineBundle] Enhancing the Doctrine 2 integration further to better handle multiple connections/entity managers

This commit is contained in:
Jonathan H. Wage 2010-02-24 19:22:10 -05:00 committed by Fabien Potencier
parent b3d8aa414e
commit 1a45bb6d63
9 changed files with 678 additions and 40 deletions

View File

@ -0,0 +1,139 @@
<?php
namespace Symfony\Framework\DoctrineBundle\Command;
use Symfony\Components\Console\Input\InputArgument;
use Symfony\Components\Console\Input\InputOption;
use Symfony\Components\Console\Input\InputInterface;
use Symfony\Components\Console\Output\OutputInterface;
use Symfony\Components\Console\Output\Output;
use Symfony\Framework\WebBundle\Util\Filesystem;
use Doctrine\Common\Cli\Configuration;
use Doctrine\Common\Cli\CliController as DoctrineCliController;
use Doctrine\DBAL\Connection;
/*
* This file is part of the symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Build command allows you to easily build and re-build your Doctrine development environment
*
* @package symfony
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Kris Wallsmith <kris.wallsmith@symfony-project.org>
*/
class BuildDoctrineCommand extends DoctrineCommand
{
const
BUILD_ENTITIES = 1,
BUILD_DB = 16,
OPTION_ENTITIES = 1,
OPTION_DB = 16,
OPTION_ALL = 31;
/**
* @see Command
*/
protected function configure()
{
$this
->setName('doctrine:build')
->setDescription('Build task for easily re-building your Doctrine development environment.')
->addOption('all', null, null, 'Build everything and reset the database')
->addOption('entities', null, null, 'Build model classes')
->addOption('db', null, null, 'Drop database, create database and create schema.')
->addOption('and-load', null, InputOption::PARAMETER_OPTIONAL | InputOption::PARAMETER_IS_ARRAY, 'Load data fixtures')
->addOption('and-append', null, InputOption::PARAMETER_OPTIONAL | InputOption::PARAMETER_IS_ARRAY, 'Load data fixtures and append to existing data')
->addOption('and-update-schema', null, null, 'Update schema after rebuilding all classes')
->addOption('connection', null, null, 'The connection to use.')
;
}
/**
* @see Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if (!$mode = $this->calculateMode($input))
{
throw new \InvalidArgumentException(sprintf("You must include one or more of the following build options:\n--%s\n\nSee this task's help page for more information:\n\n php console help doctrine:build", join(', --', array_keys($this->getBuildOptions()))));
}
if (self::BUILD_ENTITIES == (self::BUILD_ENTITIES & $mode))
{
$this->runCommand('doctrine:build-entities');
}
if (self::BUILD_DB == (self::BUILD_DB & $mode))
{
$this->runCommand('doctrine:schema-tool', array('--re-create' => true, '--connection' => $input->getOption('connection')));
}
if ($input->getOption('and-update-schema'))
{
$this->runCommand('doctrine:schema-tool', array('--update' => true, '--connection' => $input->getOption('connection')));
$this->runCommand('doctrine:schema-tool', array('--complete-update' => true, '--connection' => $input->getOption('connection')));
}
if ($input->hasOption('and-load'))
{
$dirOrFile = $input->getOption('and-load');
$this->runCommand('doctrine:load-data-fixtures',
array('--dir_or_file' => $dirOrFile, '--append' => false)
);
}
else if ($input->hasOption('and-append'))
{
$dirOrFile = $input->getOption('and-append');
$this->runCommand('doctrine:load-data-fixtures', array('--dir_or_file' => $dirOrFile, '--append' => true));
}
}
/**
* Calculates a bit mode based on the supplied options.
*
* @param InputInterface $input
* @return integer
*/
protected function calculateMode(InputInterface $input)
{
$mode = 0;
foreach ($this->getBuildOptions() as $name => $value)
{
if ($input->getOption($name) === true)
{
$mode = $mode | $value;
}
}
return $mode;
}
/**
* Returns an array of valid build options.
*
* @return array An array of option names and their mode
*/
protected function getBuildOptions()
{
$options = array();
foreach ($this->getDefinition()->getOptions() as $option)
{
if (defined($constant = __CLASS__.'::OPTION_'.str_replace('-', '_', strtoupper($option->getName()))))
{
$options[$option->getName()] = constant($constant);
}
}
return $options;
}
}

View File

@ -0,0 +1,66 @@
<?php
namespace Symfony\Framework\DoctrineBundle\Command;
use Symfony\Components\Console\Input\InputArgument;
use Symfony\Components\Console\Input\InputOption;
use Symfony\Components\Console\Input\InputInterface;
use Symfony\Components\Console\Output\OutputInterface;
use Symfony\Components\Console\Output\Output;
use Symfony\Framework\WebBundle\Util\Filesystem;
use Doctrine\Common\Cli\Configuration;
use Doctrine\Common\Cli\CliController as DoctrineCliController;
/*
* This file is part of the symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Build all Bundle entity classes from mapping information.
*
* @package symfony
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class BuildEntitiesDoctrineCommand extends DoctrineCommand
{
/**
* @see Command
*/
protected function configure()
{
$this
->setName('doctrine:build-entities')
->setDescription('Build all Bundle entity classes from mapping information.')
;
}
/**
* @see Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
foreach ($this->container->getParameter('kernel.bundle_dirs') as $bundle => $path)
{
$bundles = glob($path.'/*Bundle');
foreach ($bundles as $p)
{
if (!is_dir($metadataPath = $p.'/Resources/config/doctrine/metadata'))
{
continue;
}
$opts = array();
$opts['--from'] = $metadataPath;
$opts['--to'] = 'annotation';
$opts['--dest'] = realpath($path.'/..');
$this->runCommand('doctrine:convert-mapping', $opts);
}
}
}
}

View File

@ -0,0 +1,127 @@
<?php
namespace Symfony\Framework\DoctrineBundle\Command;
use Symfony\Components\Console\Input\InputArgument;
use Symfony\Components\Console\Input\InputOption;
use Symfony\Components\Console\Input\InputInterface;
use Symfony\Components\Console\Output\OutputInterface;
use Symfony\Components\Console\Output\Output;
use Symfony\Framework\WebBundle\Util\Filesystem;
use Doctrine\Common\Cli\Configuration;
use Doctrine\Common\Cli\CliController as DoctrineCliController;
use Doctrine\DBAL\Connection;
/*
* This file is part of the symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Database tool allows you to easily drop and create your configured databases.
*
* @package symfony
* @subpackage console
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class DatabaseToolDoctrineCommand extends DoctrineCommand
{
/**
* @see Command
*/
protected function configure()
{
$this
->setName('doctrine:database-tool')
->setDescription('Create and drop the configured databases.')
->addOption('re-create', null, null, 'Drop and re-create your databases.')
->addOption('drop', null, null, 'Drop your databases.')
->addOption('create', null, null, 'Create your databases.')
->addOption('connection', null, null, 'The connection name to work on.')
;
}
/**
* @see Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('re-create'))
{
$input->setOption('drop', true);
$input->setOption('create', true);
}
if (!$input->getOption('drop') && !$input->getOption('create'))
{
throw new \InvalidArgumentException('You must specify one of the --drop and --create options or both.');
}
$found = false;
$connections = $this->getDoctrineConnections();
foreach ($connections as $name => $connection)
{
if ($input->getOption('connection') && $name != $input->getOption('connection'))
{
continue;
}
if ($input->getOption('drop'))
{
$this->dropDatabaseForConnection($connection, $output);
}
if ($input->getOption('create'))
{
$this->createDatabaseForConnection($connection, $output);
}
$found = true;
}
if ($found === false)
{
if ($input->getOption('connection'))
{
throw new \InvalidArgumentException(sprintf('<error>Could not find a connection named <comment>%s</comment></error>', $input->getOption('connection')));
}
else
{
throw new \InvalidArgumentException(sprintf('<error>Could not find any configured connections</error>', $input->getOption('connection')));
}
}
}
protected function dropDatabaseForConnection(Connection $connection, OutputInterface $output)
{
$params = $connection->getParams();
$name = isset($params['path']) ? $params['path']:$params['dbname'];
try {
$connection->getSchemaManager()->dropDatabase($name);
$output->writeln(sprintf('<info>Dropped database for connection named <comment>%s</comment></info>', $name));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Could not drop database for connection named <comment>%s</comment></error>', $name));
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
}
}
protected function createDatabaseForConnection(Connection $connection, OutputInterface $output)
{
$params = $connection->getParams();
$name = isset($params['path']) ? $params['path']:$params['dbname'];
unset($params['dbname']);
$tmpConnection = \Doctrine\DBAL\DriverManager::getConnection($params);
try {
$tmpConnection->getSchemaManager()->createDatabase($name);
$output->writeln(sprintf('<info>Created database for connection named <comment>%s</comment></info>', $name));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Could not create database for connection named <comment>%s</comment></error>', $name));
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
}
$tmpConnection->close();
}
}

View File

@ -3,11 +3,13 @@
namespace Symfony\Framework\DoctrineBundle\Command;
use Symfony\Framework\WebBundle\Command\Command;
use Symfony\Components\Console\Input\ArrayInput;
use Symfony\Components\Console\Input\InputArgument;
use Symfony\Components\Console\Input\InputOption;
use Symfony\Components\Console\Input\InputInterface;
use Symfony\Components\Console\Output\OutputInterface;
use Symfony\Components\Console\Output\Output;
use Symfony\Framework\WebBundle\Console\Application;
use Symfony\Framework\WebBundle\Util\Filesystem;
use Doctrine\Common\Cli\Configuration;
use Doctrine\Common\Cli\CliController as DoctrineCliController;
@ -30,16 +32,19 @@ use Doctrine\Common\Cli\CliController as DoctrineCliController;
*/
abstract class DoctrineCommand extends Command
{
protected $cli;
protected
$cli,
$em;
protected function getDoctrineCli()
{
if ($this->cli === null)
{
$configuration = new Configuration();
$configuration->setAttribute('em', $this->container->getDoctrine_Orm_EntityManagerService());
$this->cli = new DoctrineCliController($configuration);
}
$em = $this->em ? $this->em : $this->container->getDoctrine_Orm_EntityManagerService();
$this->cli->getConfiguration()->setAttribute('em', $em);
return $this->cli;
}
@ -60,7 +65,7 @@ abstract class DoctrineCommand extends Command
return $this->getDoctrineCli()->run(array_merge(array('doctrine', $name), $builtOptions));
}
public function buildDoctrineCliTaskOptions(InputInterface $input, array $options)
protected function buildDoctrineCliTaskOptions(InputInterface $input, array $options)
{
$taskOptions = array();
foreach ($options as $option)
@ -72,4 +77,49 @@ abstract class DoctrineCommand extends Command
}
return $options;
}
protected function runCommand($name, array $input = array())
{
$arguments = array();
$arguments = array_merge(array($name), $input);
$input = new ArrayInput($arguments);
$application = new Application($this->container->getKernelService());
$application->setAutoExit(false);
$application->run($input);
}
/**
* TODO: Better way to do these functions?
*/
protected function getDoctrineConnections()
{
$connections = array();
$ids = $this->container->getServiceIds();
foreach ($ids as $id)
{
preg_match('/doctrine.dbal.(.*)_connection/', $id, $matches);
if ($matches)
{
$name = $matches[1];
$connections[$name] = $this->container->getService($id);
}
}
return $connections;
}
protected function getDoctrineEntityManagers()
{
$entityManagers = array();
$ids = $this->container->getServiceIds();
foreach ($ids as $id)
{
preg_match('/doctrine.orm.(.*)_entity_manager/', $id, $matches);
if ($matches)
{
$name = $matches[1];
$entityManagers[$name] = $this->container->getService($id);
}
}
return $entityManagers;
}
}

View File

@ -41,7 +41,7 @@ class LoadDataFixturesDoctrineCommand extends DoctrineCommand
$this
->setName('doctrine:load-data-fixtures')
->setDescription('Load data fixtures to your database.')
->addOption('dir_or_file', null, null, 'The directory or file to load data fixtures from.')
->addOption('dir_or_file', null, InputOption::PARAMETER_OPTIONAL | InputOption::PARAMETER_IS_ARRAY, 'The directory or file to load data fixtures from.')
->addOption('append', null, InputOption::PARAMETER_OPTIONAL, 'Whether or not to append the data fixtures.', false)
;
}
@ -51,37 +51,11 @@ class LoadDataFixturesDoctrineCommand extends DoctrineCommand
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->container->getDoctrine_ORM_EntityManagerService();
if (!$input->getOption('append'))
{
$classes = array();
$metadatas = $em->getMetadataFactory()->getAllMetadata();
foreach ($metadatas as $metadata)
{
if (!$metadata->isMappedSuperclass)
{
$classes[] = $metadata;
}
}
$cmf = $em->getMetadataFactory();
$classes = $this->getCommitOrder($em, $classes);
for ($i = count($classes) - 1; $i >= 0; --$i)
{
$class = $classes[$i];
if ($cmf->hasMetadataFor($class->name))
{
try {
$em->createQuery('DELETE FROM '.$class->name.' a')->execute();
} catch (Exception $e) {}
}
}
}
$defaultEm = $this->container->getDoctrine_ORM_EntityManagerService();
$dirOrFile = $input->getOption('dir_or_file');
if ($dirOrFile)
{
$paths = $dirOrFile;
$paths = is_array($dirOrFile) ? $dirOrFile : array($dirOrFile);
} else {
$paths = array();
$bundleDirs = $this->container->getKernelService()->getBundleDirs();
@ -112,23 +86,86 @@ class LoadDataFixturesDoctrineCommand extends DoctrineCommand
$files = array_merge($files, $found);
}
$ems = array();
$emEntities = array();
$files = array_unique($files);
foreach ($files as $file)
{
$em = $defaultEm;
$output->writeln(sprintf('<info>Loading data fixtures from <comment>"%s"</comment></info>', $file));
$before = array_keys(get_defined_vars());
include($file);
$after = array_keys(get_defined_vars());
$new = array_diff($after, $before);
$entities = array_values($new);
unset($entities[array_search('before', $entities)]);
foreach ($entities as $entity) {
$em->persist($$entity);
$params = $em->getConnection()->getParams();
$emName = isset($params['path']) ? $params['path']:$params['dbname'];
$ems[$emName] = $em;
$emEntities[$emName] = array();
$variables = array_values($new);
foreach ($variables as $variable)
{
$value = $$variable;
if (!is_object($value) || $value instanceof \Doctrine\ORM\EntityManager)
{
continue;
}
$emEntities[$emName][] = $value;
}
foreach ($ems as $emName => $em)
{
if (!$input->getOption('append'))
{
$output->writeln(sprintf('<info>Purging data from entity manager named <comment>"%s"</comment></info>', $emName));
$this->purgeEntityManager($em);
}
$entities = $emEntities[$emName];
$numEntities = count($entities);
$output->writeln(sprintf('<info>Persisting "%s" '.($numEntities > 1 ? 'entities' : 'entity').'</info>', count($entities)));
foreach ($entities as $entity)
{
$output->writeln(sprintf('<info>Persisting "%s" entity:</info>', get_class($entity)));
$output->writeln('');
$output->writeln(var_dump($entity));
$em->persist($entity);
}
$output->writeln('<info>Flushing entity manager</info>');
$em->flush();
}
$em->flush();
}
}
protected function purgeEntityManager(EntityManager $em)
{
$classes = array();
$metadatas = $em->getMetadataFactory()->getAllMetadata();
foreach ($metadatas as $metadata)
{
if (!$metadata->isMappedSuperclass)
{
$classes[] = $metadata;
}
}
$cmf = $em->getMetadataFactory();
$classes = $this->getCommitOrder($em, $classes);
for ($i = count($classes) - 1; $i >= 0; --$i)
{
$class = $classes[$i];
if ($cmf->hasMetadataFor($class->name))
{
try {
$em->createQuery('DELETE FROM '.$class->name.' a')->execute();
} catch (Exception $e) {}
}
}
}
protected function getCommitOrder(EntityManager $em, array $classes)
{
$calc = new CommitOrderCalculator;
@ -154,4 +191,4 @@ class LoadDataFixturesDoctrineCommand extends DoctrineCommand
return $calc->getCommitOrder();
}
}
}

View File

@ -40,6 +40,7 @@ class RunDqlDoctrineCommand extends DoctrineCommand
->setDescription('Executes arbitrary DQL directly from the command line.')
->addOption('dql', null, null, 'The DQL query to run.')
->addOption('depth', null, null, 'The depth to output the data to.')
->addOption('connection', null, null, 'The connection to use.')
;
}

View File

@ -41,6 +41,7 @@ class RunSqlDoctrineCommand extends DoctrineCommand
->addOption('sql', null, null, 'The SQL query to run.')
->addOption('file', null, null, 'Path to a SQL file to run.')
->addOption('depth', null, null, 'The depth to output the data to.')
->addOption('connection', null, null, 'The connection to use.')
;
}

View File

@ -44,6 +44,7 @@ class SchemaToolDoctrineCommand extends DoctrineCommand
->addOption('complete-update', null, null, 'Complete update and drop anything that is not in your schema.')
->addOption('re-create', null, null, 'Drop and re-create your database schema.')
->addOption('dump-sql', null, null, 'Dump the SQL instead of executing it.')
->addOption('connection', null, null, 'The connection to use.')
;
}
@ -55,8 +56,33 @@ class SchemaToolDoctrineCommand extends DoctrineCommand
$options = $this->buildDoctrineCliTaskOptions($input, array(
'create', 'drop', 'update', 'complete-update', 're-create', 'dump-sql'
));
$entityDirs = $this->container->getParameter('doctrine.orm.entity_dirs');
$options['class-dir'] = implode(', ', $entityDirs);
$this->runDoctrineCliTask('orm:schema-tool', $options);
$found = false;
$ems = $this->getDoctrineEntityManagers();
foreach ($ems as $name => $em)
{
if ($input->getOption('connection') && $name !== $input->getOption('connection'))
{
continue;
}
$this->em = $em;
$this->runDoctrineCliTask('orm:schema-tool', $options);
$found = true;
}
if ($found === false)
{
if ($input->getOption('connection'))
{
$output->writeln(sprintf('<error>Could not find a connection named <comment>%s</comment></error>', $input->getOption('connection')));
}
else
{
$output->writeln(sprintf('<error>Could not find any configured connections</error>', $input->getOption('connection')));
}
}
}
}

View File

@ -0,0 +1,191 @@
DoctrineBundle
--------------
This document describes some of the functionality provided by the
**DoctrineBundle**. Doctrine 2 is a first class citizen in Symfony 2 and is
tightly integrated. Continue reading to learn how to use Doctrine 2 with the
latest Symfony 2!
## Configuration
This section will help you with configuring your Symfony 2 project to enable
the Doctrine DBAL and ORM services.
### Database Abstraction Layer
You can configure your database abstraction layer simply configuration a few
pieces of information about your database. If you only have one database you can
do the following:
[yml]
doctrine.dbal:
dbname: symfony_guestbook
user: root
password: ~
Or if you have multiple connections and want to customize the configuration of the
connection further you can use the following:
[yml]
doctrine.dbal:
default_connection: default
connections:
default:
driver: PDOSqlite # PDOSqlite, PDOMySql, PDOMsSql, PDOOracle, PDOPgSql, OCI8
dbname: symfony
user: root
password: null
host: localhost
port: ~
path: %kernel.data_dir%/symfony.sqlite
event_manager_class: Doctrine\Common\EventManager
configuration_class: Doctrine\DBAL\Configuration
wrapper_class: ~
options: []
### Object Relational Mapper
If you want to enable the Doctrine 2 ORM you can do so with the following:
doctrine.orm:
default_entity_manager: default
metadata_driver: xml # xml, yml, annotation
cache_driver: apc # array, apc, memcache, xcache
entity_managers:
default:
connection: default
It's pretty simple, you can specify which entity managers you want to instantiate
for which connections and also configure some other information about the ORM
like what type of mapping files to use or what cache driver to use.
## Creating a Bundle
To get started we need to create a new bundle:
$ php console init:bundle "Bundle\\GuestbookBundle"
Initializing bundle "GuestbookBundle" in "/path/to/symfony-sandbox/src/Bundle"
Now basically the most important thing to know about using Doctrine 2 with Symfony
is where to put your mapping information files, where your entity classes are and
a few commands to help move things faster!
## Mapping Information
You can place all your mapping information inside a bundle. Below is an example
path for the **GuestbookBundle** we created above:
/path/to/symfony-sandbox/src/Bundle/GuestbookBundle/Resources/config/doctrine/metadata
Any files found in here that have a suffix of **.dcm.xml** (or whatever
mapping_driver you picked) are used as your entities mapping information.
In the **GuestbookBundle** we have a file named **Bundle.GuestbookBundle.Entities.Entry.dcm.xml**
which contains the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Bundle\GuestbookBundle\Entities\Entry" table="guestbook_entry">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="createdAt" column="created_at" type="datetime" />
<field name="name" column="name" type="string" length="255" />
<field name="emailAddress" column="email_address" type="string" length="255" />
<field name="body" column="body" type="text" />
</entity>
</doctrine-mapping>
## Building Entities
Doctrine can help you a little bit by generating the entity classes for your
mapping information with the command:
$ php console doctrine:build-entities
Now if you have a look in the bundles **Entities** directory you will see a new
file named **Entry.php** with some code like the following:
[php]
// Bundle/GuestbookBundle/Entities/Entry.php
namespace Bundle\GuestbookBundle\Entities;
/**
* @Entity
* @Table(name="guestbook_entry")
*/
class Entry
{
/**
* @Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* @Column(name="name", type="string", length=255)
*/
private $name;
// ...
> **NOTE**
> If you modify your mapping information and re-run the build entities command
> it will modify the classes and update them based on the mapping information.
## Commands
The Doctrine 2 CLI is integrated with the Symfony 2 CLI so we have all the common
commands we need to make working with Doctrine 2 just as easy and fast as before!
$ php console list doctrine
Available commands for the "doctrine" namespace:
:build Build task for easily re-building your Doctrine development environment.
:build-entities Build all Bundle entity classes from mapping information.
:clear-cache Clear cache from configured query, result and metadata drivers. (doctrine:cc)
:convert-mapping Convert mapping information between supported formats.
:database-tool Create and drop the configured databases.
:ensure-production-settings Verify that Doctrine is properly configured for a production environment.
:generate-proxies Generates proxy classes for entity classes.
:load-data-fixtures Load data fixtures to your database.
:run-dql Executes arbitrary DQL directly from the command line.
:run-sql Executes arbitrary SQL from a file or directly from the command line.
:schema-tool Processes the schema and either apply it directly on EntityManager or generate the SQL output.
:version Displays the current installed Doctrine version.
The development workflow is very similar to how it is in Symfony 1.4. You can modify
your mapping information and use **doctrine:build --all** to re-build your
environment:
php console doctrine:build --all
The recommend way to work is to re-build your entities and update your database
schema:
php console doctrine:build --entities --and-update-schema
Now any changes you made in your mapping information will be reflected in the
according databases! Here are all the available options for the **build** task:
$ php console help doctrine:build
Usage:
Symfony doctrine:build [--all] [--all-classes] [--entities] [--db] [--and-load[="..."]] [--and-append[="..."]] [--and-update-schema] [--dump-sql] [--connection]
Options:
--all Build everything and reset the database
--entities Build model classes
--db Drop database, create database and create schema.
--and-load Load data fixtures (multiple values allowed)
--and-append Load data fixtures and append to existing data (multiple values allowed)
--and-update-schema Update schema after rebuilding all classes
--connection The connection to use.