Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Initial ResolveTargetEntityListener cookbook entry #101

Merged
merged 1 commit into from

2 participants

Tim Nagel Benjamin Eberlei
Tim Nagel

As asked, a non symfony2 related RTEL example for the cookbook, ready for linting.

Benjamin Eberlei beberlei merged commit 1f2050f into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 16, 2012
  1. Tim Nagel
This page is out of date. Refresh to see the latest.
Showing with 136 additions and 0 deletions.
  1. +136 −0 en/cookbook/resolve-target-entity-listener.rst
136 en/cookbook/resolve-target-entity-listener.rst
View
@@ -0,0 +1,136 @@
+Keeping your Modules independent
+=================================
+
+One of the goals of using modules is to create discreet units of functionality
+that do not have many (if any) dependencies, allowing you to use that
+functionality in other applications without including unnecessary items.
+
+Doctrine 2.2 includes a new utility called the ``ResolveTargetEntityListener``,
+that functions by intercepting certain calls inside Doctrine and rewrite
+targetEntity parameters in your metadata mapping at runtime. It means that
+in your bundle you are able to use an interface or abstract class in your
+mappings and expect correct mapping to a concrete entity at runtime.
+
+This functionality allows you to define relationships between different entities
+but not making them hard dependencies.
+
+Background
+----------
+
+In the following example, the situation is we have an `InvoiceModule`
+which provides invoicing functionality, and a `CustomerModule` that
+contains customer management tools. We want to keep these separated,
+because they can be used in other systems without each other, but for
+our application we want to use them together.
+
+In this case, we have an ``Invoice`` entity with a relationship to a
+non-existant object, an ``InvoiceSubjectInterface``. The goal is to get
+the ``ResolveTargetEntityListener`` to replace any mention of the interface
+with a real object that implements that interface.
+
+Set up
+------
+
+We're going to use the following basic entities (which are incomplete
+for brevity) to explain how to set up and use the RTEL.
+
+A Customer entity
+
+.. code-block:: php
+
+ // src/Acme/AppModule/Entity/Customer.php
+
+ namespace Acme\AppModule\Entity;
+
+ use Doctrine\ORM\Mapping as ORM;
+ use Acme\CustomerModule\Entity\Customer as BaseCustomer;
+ use Acme\InvoiceModule\Model\InvoiceSubjectInterface;
+
+ /**
+ * @ORM\Entity
+ * @ORM\Table(name="customer")
+ */
+ class Customer extends BaseCustomer implements InvoiceSubjectInterface
+ {
+ // In our example, any methods defined in the InvoiceSubjectInterface
+ // are already implemented in the BaseCustomer
+ }
+
+An Invoice entity
+
+.. code-block:: php
+
+ // src/Acme/InvoiceModule/Entity/Invoice.php
+
+ namespace Acme\InvoiceModule\Entity;
+
+ use Doctrine\ORM\Mapping AS ORM;
+ use Acme\InvoiceModule\Model\InvoiceSubjectInterface;
+
+ /**
+ * Represents an Invoice.
+ *
+ * @ORM\Entity
+ * @ORM\Table(name="invoice")
+ */
+ class Invoice
+ {
+ /**
+ * @ORM\ManyToOne(targetEntity="Acme\InvoiceModule\Model\InvoiceSubjectInterface")
+ * @var InvoiceSubjectInterface
+ */
+ protected $subject;
+ }
+
+An InvoiceSubjectInterface
+
+.. code-block:: php
+
+ // src/Acme/InvoiceModule/Model/InvoiceSubjectInterface.php
+
+ namespace Acme\InvoiceModule\Model;
+
+ /**
+ * An interface that the invoice Subject object should implement.
+ * In most circumstances, only a single object should implement
+ * this interface as the ResolveTargetEntityListener can only
+ * change the target to a single object.
+ */
+ interface InvoiceSubjectInterface
+ {
+ // List any additional methods that your InvoiceModule
+ // will need to access on the subject so that you can
+ // be sure that you have access to those methods.
+
+ /**
+ * @return string
+ */
+ public function getName();
+ }
+
+Next, we need to configure the listener. Add this to the area you set up Doctrine. You
+must set this up in the way outlined below, otherwise you can not be guaranteed that
+the targetEntity resolution will occur reliably::
+
+.. code-block:: php
+
+ $evm = new \Doctrine\Common\EventManager;
+
+ $rtel = new \Doctrine\ORM\Tools\ResolveTargetEntityListener;
+ $rtel->addResolveTargetEntity('Acme\\InvoiceModule\\Model\\InvoiceSubjectInterface',
+ 'Acme\\CustomerModule\\Entity\\Customer', array());
+
+ // Add the ResolveTargetEntityListener
+ $evm->addEventSubscriber($rtel);
+
+ $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm);
+
+Final Thoughts
+--------------
+
+With the ``ResolveTargetEntityListener``, we are able to decouple our
+bundles, keeping them usable by themselves, but still being able to
+define relationships between different objects. By using this method,
+I've found my bundles end up being easier to maintain independently.
+
+
Something went wrong with that request. Please try again.