From d345d0043258165af11f8843bac0cfc29cbee97a Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Tue, 5 Oct 2010 22:02:18 +0200 Subject: [PATCH 1/4] Add docs on Doctrine ORM Form integration --- guides/doctrine/orm/form.rst | 75 +++++++++++++++++++++++++++++++++++ guides/doctrine/orm/index.rst | 1 + 2 files changed, 76 insertions(+) create mode 100644 guides/doctrine/orm/form.rst diff --git a/guides/doctrine/orm/form.rst b/guides/doctrine/orm/form.rst new file mode 100644 index 00000000000..dea5deb75bd --- /dev/null +++ b/guides/doctrine/orm/form.rst @@ -0,0 +1,75 @@ +Form Integration +================ + +There is a tight integration between Doctrine ORM and the Symfony Form component. Since Doctrine Entities +are plain old php objects they nicely integrate into the Form component by default, at least for the +primitive data types such as strings, integers and fields. However you can also integrate them nicely +with associations. + +This is done by the help of ValueTransformers, which are form field extension points. There are currently +three transformers that allow you to transform Doctrine ORM Collections and Entities into their identifier +values that can be used with the Form component. Furthermore they translate form values back to the Doctrine +representation in the most efficient way possible, issuing as few queries as possible. + +CollectionToChoiceTransformer +----------------------------- + +This transformer allows you to transform a Collection of Entities into an array of ids. This transformer +should be used with the ChoiceField or any compatible field that handles arrays of values. + + use Symfony\Component\Form\ChoiceField; + use Symfony\Bundle\DoctrineBundle\Form\ValueTransformer\CollectionToChoiceTransformer; + + $field = new ChoiceField('products', array( + 'choices' => $productChoices, + 'multiple' => true, + 'expanded' => true, + )); + $field->setValueTransformer(new CollectionToChoiceTransformer(array( + 'em' => $em, + 'className' => 'Product', + ))); + + // Important: Make sure to attach the value transformer before calling addField(). + $form->addField($field); + +The 'em' property expects the EntityManager, the 'className' property expects the Entity Class name +as an argument. + +CollectionToStringTransformer +----------------------------- + +This transformer allows you to transform a Collection of Entities into a string separated by a separator. +This is useful for lists of tags, usernames or similiar unique fields of your Entities. + +EntityToIDTransformer +--------------------- + +This transformer converts an Entity into its ID and back to allow to select many-to-one +or one-to-one entities in choice fields. See this extended example on how it works. In this +case a list of all users is used in a Choice field to be choosen from: + + use Symfony\Bundle\DoctrineBundle\Form\ValueTransformer\EntityToIDTransformer; + use Symfony\Component\Form\ChoiceField; + + $userChoices = array(); + $users = $em->getRepository('User')->findAll(); + foreach ($users AS $user) { + $userChoices[$user->id] = $user->name; + } + + $userTransformer = new EntityToIDTransformer(array( + 'em' => $em, + 'className' => 'User', + )); + $engineerField = new ChoiceField('engineer', array( + 'choices' => $userChoices, + )); + $engineerField->setValueTransformer($userTransformer); + $reporterField = new ChoiceField('reporter', array( + 'choices' => $userChoices, + )); + $reporterField->setValueTransformer($userTransformer); + + $form->add($engineerField); + $form->add($reporterfield); \ No newline at end of file diff --git a/guides/doctrine/orm/index.rst b/guides/doctrine/orm/index.rst index 3cc24717d76..7627761bbef 100644 --- a/guides/doctrine/orm/index.rst +++ b/guides/doctrine/orm/index.rst @@ -7,3 +7,4 @@ Object Relational Mapper Overview Configuration Console Commands + Form
\ No newline at end of file From 4ffb90b67a8139d3eb06165ef00195d3492534ad Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Thu, 30 Dec 2010 20:36:57 +0100 Subject: [PATCH 2/4] Update Doctrine ORM Docs with new mapping configuration details. --- guides/doctrine/orm/configuration.rst | 139 +++++++++++++++++++++----- guides/doctrine/orm/overview.rst | 45 ++++++++- 2 files changed, 154 insertions(+), 30 deletions(-) diff --git a/guides/doctrine/orm/configuration.rst b/guides/doctrine/orm/configuration.rst index 12bcf4a64ca..984798ef5d6 100644 --- a/guides/doctrine/orm/configuration.rst +++ b/guides/doctrine/orm/configuration.rst @@ -5,6 +5,109 @@ Configuration ============= +In the overview we already described the only necessary configuration option "mappings" +to get the Doctrine ORM running with Symfony 2. All the other configuration options are +used with reasonable default values. + +This following configuration example shows all the configuration defaults that the ORM resolves to: + +.. code-block:: yaml + + doctrine.orm: + mappings: + HelloBundle: ~ + auto_generate_proxy_classes: true + proxy_namespace: Proxies + proxy_dir: %kernel.cache_dir%/doctrine/orm/Proxies + default_entity_manager: default + default_connection: default + metadata_cache_driver: array + query_cache_driver: array + result_cache_driver: array + +There are lots of other configuration options that you can use to overwrite certain classes, but those +are for very advanced use-cases only. You should look at the "orm.xml" file in the DoctrineBundle to +get an overview of all the supported options. + +For the caching drivers you can specifiy the values "array", "apc", "memcache" or "xcache". + +The following example shows an overview of the caching configurations: + +.. code-block:: yaml + + doctrine.orm: + mappings: + HelloBundle: ~ + metadata_cache_driver: apc + query_cache_driver: xcache + result_cache_driver: + type: memcache + host: localhost + port: 11211 + instance_class: Memcache + +Mapping Configuration +~~~~~~~~~~~~~~~~~~~~~ + +Explicit definition of all the mapped entities is the only necessary configuration for the ORM and there +are several configuration options that you can control. The following configuration options exist +for a mapping: + +- ``type`` One of "annotations", "xml", "yml", "php" or "static-php". This specifies which type + of metadata type your mapping uses. +- ``dir`` Path to the mapping or entity files (depending on the driver). If this path is relative + it is assumed to be relative to the bundle root. This only works if the name of your mapping + is a bundle name. If you want to use this option to specifiy absolute paths you should prefix + the path with the kernel parameters that exist in the DIC (for example %kernel.dir%). +- ``prefix`` A common namespace prefix that all entities of this mapping share. This prefix + should never conflict with prefixes of other defined mappings otherwise some of your entities cannot be found + by Doctrine. This option defaults to the bundle namespace + `Entities`, for example for an + application bundle called "Hello" prefix would be "Application\Hello\Entities". +- ``alias`` Doctrine offers a way to alias entity namespaces to simpler, shorter names to be used + in DQL queries or for Repository access. +- ``is_bundle`` This option is a derived value from ``dir`` and by default is set to true if dir is relative + proved by a ``file_exists()`` check that returns false. It is false if the existance check returns true. + In this case an absolute path was specified and the metadata files are most likely in a directory outside of + a bundle. + +To avoid having to configure lots of information for your mappings you should follow these conventions: + +1. Put all your entities in a directory Entities/ inside your bundle. For example "Application/Hello/Entities/". +2. If you are using xml, yml or php mapping put all your configuration files into the + "Resources/config/doctrine/metadata/doctrine/orm/" directory sufficed with dcm.xml, dcm.yml or dcm.php + respectively. +3. Annotations is assumed if an "Entities/" but no "Resources/config/doctrine/metadata/doctrine/orm/" + directory is found. + +The following configuration shows a bunch of mapping examples: + +.. code-block:: yaml + + doctrine.orm: + mappings: + MyBundle1: ~ + MyBundle2: yml + MyBundle3: { type: annotation, dir: Entities/ } + MyBundle4: { type: xml, dir: Resources/config/doctrine/mapping } + MyBundle5: + type: yml + dir: my-bundle-mappings-dir + alias: BundleAlias + doctrine_extensions: + type: xml + dir: %kernel.dir%/../src/vendor/DoctrineExtensions/lib/DoctrineExtensions/Entities + prefix: DoctrineExtensions\Entities\ + alias: DExt + +Multiple Entity Managers +~~~~~~~~~~~~~~~~~~~~~~~~ + +You can use multiple EntityManagers in a Symfony application. This is necessary +if you are using different databases or even vendors with entirely different sets +of entities. + +The following configuration code shows how to define two EntityManagers: + .. code-block:: yaml doctrine.orm: @@ -17,37 +120,21 @@ Configuration connection: customer Just like the DBAL, if you have configured multiple ``EntityManager`` instances -and want to get a specific one you can use the ``getEntityManager()`` method by -just passing it an argument that is the ``EntityManager`` name you want:: +and want to get a specific one you can use the full service name to retrieve +it from the Symfony Dependency Injection Container: class UserController extends Controller { public function indexAction() { - $em = $this->get('doctrine.orm.customer_entity_manager'); - } - } - -Now the scenario arrises where you want to change your mapping information and -update your development database schema without blowing away everything and -losing your existing data. So first lets just add a new property to our ``User`` -entity:: - - namespace Application\HelloBundle\Entities; - - /** @orm:Entity */ - class User - { - /** @orm:Column(type="string") */ - protected $new; + $em = $this->get('doctrine.orm.entity_manager'); + $defaultEm = $this->get('doctrine.orm.default_entity_manager'); + $customerEm = $this->get('doctrine.orm.customer_entity_manager'); - // ... + // $em === $defaultEm => true + // $defaultEm === $customerEm => false + } } -Once you've done that, to get your database schema updated with the new column -you just need to run the following command: - - $ php app/console doctrine:schema:update - -Now your database will be updated and the new column added to the database -table. +The service "doctrine.orm.entity_manager" is an alias for the default entity manager +defined in the "default_entity_manager" configuration option. \ No newline at end of file diff --git a/guides/doctrine/orm/overview.rst b/guides/doctrine/orm/overview.rst index 6113afc7770..f2bb7770a6b 100644 --- a/guides/doctrine/orm/overview.rst +++ b/guides/doctrine/orm/overview.rst @@ -14,25 +14,34 @@ persistence for PHP objects. official `documentation`_ website. To get started, enable and configure the :doc:`Doctrine DBAL -`, then enable the ORM: +`, then enable the ORM. The minimal +necessary configuration is to specify the bundle name which contains your entities. .. configuration-block:: .. code-block:: yaml # app/config/config.yml - doctrine.orm: ~ + doctrine.orm: + mappings: + HelloBundle: ~ .. code-block:: xml - + + + + + .. code-block:: php - $container->loadFromExtension('doctrine', 'orm'); + $container->loadFromExtension('doctrine', 'orm', array( + "mappings" => array("HelloBundle" => array()), + )); As Doctrine provides transparent persistence for PHP objects, it works with any PHP class:: @@ -145,6 +154,9 @@ the following commands: Eventually, use your entity and manage its persistent state with Doctrine:: + // Application/HelloBundle/Controller/UserController.php + namespace Application\HelloBundle\Controller; + use Application\HelloBundle\Entity\User; class UserController extends Controller @@ -183,5 +195,30 @@ Eventually, use your entity and manage its persistent state with Doctrine:: } } +Now the scenario arrises where you want to change your mapping information and +update your development database schema without blowing away everything and +losing your existing data. So first lets just add a new property to our ``User`` +entity:: + + namespace Application\HelloBundle\Entities; + + /** @orm:Entity */ + class User + { + /** @orm:Column(type="string") */ + protected $new; + + // ... + } + +Once you've done that, to get your database schema updated with the new column +you just need to run the following command: + + $ php app/console doctrine:schema:update + +Now your database will be updated and the new column added to the database +table. + + .. _documentation: http://www.doctrine-project.org/projects/orm/2.0/docs/en .. _Doctrine: http://www.doctrine-project.org From 63e9e5a202d94a40584ba13ed50ddbcff75b3b51 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Thu, 30 Dec 2010 20:39:49 +0100 Subject: [PATCH 3/4] Update Doctrine MongoDB docs with new mapping configuration details. --- guides/doctrine/mongodb-odm/configuration.rst | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/guides/doctrine/mongodb-odm/configuration.rst b/guides/doctrine/mongodb-odm/configuration.rst index eb288a42c65..b789f9bb982 100644 --- a/guides/doctrine/mongodb-odm/configuration.rst +++ b/guides/doctrine/mongodb-odm/configuration.rst @@ -33,6 +33,59 @@ If you wish to use memcache to cache your metadata, you need to configure the port: 11211 instance_class: Memcache +Mapping Configuration +~~~~~~~~~~~~~~~~~~~~~ + +Explicit definition of all the mapped documents is the only necessary configuration for the ODM and there +are several configuration options that you can control. The following configuration options exist +for a mapping: + +- ``type`` One of "annotations", "xml", "yml", "php" or "static-php". This specifies which type + of metadata type your mapping uses. +- ``dir`` Path to the mapping or entity files (depending on the driver). If this path is relative + it is assumed to be relative to the bundle root. This only works if the name of your mapping + is a bundle name. If you want to use this option to specifiy absolute paths you should prefix + the path with the kernel parameters that exist in the DIC (for example %kernel.dir%). +- ``prefix`` A common namespace prefix that all documents of this mapping share. This prefix + should never conflict with prefixes of other defined mappings otherwise some of your documents cannot be found + by Doctrine. This option defaults to the bundle namespace + `Documents`, for example for an + application bundle called "Hello" prefix would be "Application\Hello\Documents". +- ``alias`` Doctrine offers a way to alias document namespaces to simpler, shorter names to be used + inqueries or for Repository access. +- ``is_bundle`` This option is a derived value from ``dir`` and by default is set to true if dir is relative + proved by a ``file_exists()`` check that returns false. It is false if the existance check returns true. + In this case an absolute path was specified and the metadata files are most likely in a directory outside of + a bundle. + +To avoid having to configure lots of information for your mappings you should follow these conventions: + +1. Put all your entities in a directory Documents/ inside your bundle. For example "Application/Hello/Documents/". +2. If you are using xml, yml or php mapping put all your configuration files into the + "Resources/config/doctrine/metadata/doctrine/mongodb/" directory sufficed with dcm.xml, dcm.yml or dcm.php + respectively. +3. Annotations is assumed if an "Documents/" but no "Resources/config/doctrine/metadata/doctrine/mongodb/" + directory is found. + +The following configuration shows a bunch of mapping examples: + +.. code-block:: yaml + + doctrine.mongodb: + mappings: + MyBundle1: ~ + MyBundle2: yml + MyBundle3: { type: annotation, dir: Documents/ } + MyBundle4: { type: xml, dir: Resources/config/doctrine/mapping } + MyBundle5: + type: yml + dir: my-bundle-mappings-dir + alias: BundleAlias + doctrine_extensions: + type: xml + dir: %kernel.dir%/../src/vendor/DoctrineExtensions/lib/DoctrineExtensions/Documents + prefix: DoctrineExtensions\Documents\ + alias: DExt + Multiple Connections ~~~~~~~~~~~~~~~~~~~~ From 96b74b54aa2317c67cc4aafbd524040444226e41 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Thu, 30 Dec 2010 20:42:42 +0100 Subject: [PATCH 4/4] Missing change in the overview of MongoDB docs. --- guides/doctrine/mongodb-odm/overview.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/guides/doctrine/mongodb-odm/overview.rst b/guides/doctrine/mongodb-odm/overview.rst index cdf16533fed..d19d8f80acf 100644 --- a/guides/doctrine/mongodb-odm/overview.rst +++ b/guides/doctrine/mongodb-odm/overview.rst @@ -14,13 +14,15 @@ persisted transparently without imposing on your domain model. projects `documentation`_. To get started working with Doctrine and the MongoDB Object Document Mapper you -just need to enable it: +just need to enable it and specify the bundle that contains your mapped documents: .. code-block:: yaml # app/config/config.yml - doctrine_odm.mongodb: ~ + doctrine_odm.mongodb: + mappings: + HelloBundle: ~ Now you can start writing documents and mapping them with annotations, xml, or yaml. In this example we will use annotations::