From e6ba3a96ec8c28f692dedb1bc22a423868aad574 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 27 May 2025 12:02:55 +0200 Subject: [PATCH] Rewords --- doctrine.rst | 28 +++++++------ doctrine/resolve_target_entity.rst | 67 ++++++++++++++---------------- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/doctrine.rst b/doctrine.rst index e66488beef..ecaf675df0 100644 --- a/doctrine.rst +++ b/doctrine.rst @@ -789,22 +789,26 @@ variable. Let's say you want the first or the last comment of a product dependin Fetch via Interfaces ~~~~~~~~~~~~~~~~~~~~ -Suppose your ``Product`` object implements an interface called ``ProductInterface``. -If you want to decouple your controllers from your entity implementations, you can instead reference entities via an interface. -To do this, first you need to configure the :doc:`resolve_target_entities option `. - -Your controller can then reference the Product entity by its interface instead:: +Suppose your ``Product`` class implements an interface called ``ProductInterface``. +If you want to decouple your controllers from the concrete entity implementation, +you can reference the entity by its interface instead. - public function show( - #[MapEntity] - ProductInterface $product - ): Response { - // ... - } +To enable this, first configure the +:doc:`resolve_target_entities option `. +Then, your controller can type-hint the interface, and the entity will be +resolved automatically:: + + public function show( + #[MapEntity] + ProductInterface $product + ): Response { + // ... + } .. versionadded:: 7.3 - Support for ``resolve_target_entites`` in the ``EntityValueResolver`` was introduced in Symfony 7.3. + Support for target entity resolution in the ``EntityValueResolver`` was + introduced Symfony 7.3 MapEntity Options ~~~~~~~~~~~~~~~~~ diff --git a/doctrine/resolve_target_entity.rst b/doctrine/resolve_target_entity.rst index c55b27f646..1495f47562 100644 --- a/doctrine/resolve_target_entity.rst +++ b/doctrine/resolve_target_entity.rst @@ -1,44 +1,45 @@ Referencing Entities with Abstract Classes and Interfaces ========================================================= -In applications where functionality is segregated with minimal concrete dependencies -between the various layers, such as monoliths which are split into multiple modules, -it might be hard to prevent hard dependencies on entities between modules. +In applications where functionality is organized in layers or modules with +minimal concrete dependencies, such as monoliths split into multiple modules, +it can be challenging to avoid tight coupling between entities. -Doctrine 2.2 includes a new utility called the ``ResolveTargetEntityListener``, -that functions by intercepting certain calls inside Doctrine and rewriting -``targetEntity`` parameters in your metadata mapping at runtime. It means that -you are able to use an interface or abstract class in your mappings and expect -correct mapping to a concrete entity at runtime. +Doctrine provides a utility called the ``ResolveTargetEntityListener`` to solve +this issue. It works by intercepting certain calls within Doctrine and rewriting +``targetEntity`` parameters in your metadata mapping at runtime. This allows you +to reference an interface or abstract class in your mappings and have it resolved +to a concrete entity at runtime. -This functionality allows you to define relationships between different entities -without making them hard dependencies. +This makes it possible to define relationships between entities without +creating hard dependencies. This feature also works with the ``EntityValueResolver`` +:ref:`as explained in the main Doctrine article `. -.. tip:: +.. versionadded:: 7.3 - Starting with Symfony 7.3, this functionality also works with the ``EntityValueResolver``. - See :ref:`doctrine-entity-value-resolver-resolve-target-entities` for more details. + Support for target entity resolution in the ``EntityValueResolver`` was + introduced Symfony 7.3 Background ---------- -Suppose you have an application which provides two modules; an Invoice module which -provides invoicing functionality, and a Customer module that contains customer management -tools. You want to keep dependencies between these modules separated, because they should -not be aware of the other module's implementation details. +Suppose you have an application with two modules: an Invoice module that +provides invoicing functionality, and a Customer module that handles customer +management. You want to keep these modules decoupled, so that neither is aware +of the other's implementation details. -In this case, you have an ``Invoice`` entity with a relationship to the interface -``InvoiceSubjectInterface``. This is not recognized as a valid entity by Doctrine. -The goal is to get the ``ResolveTargetEntityListener`` to replace any mention of the interface -with a real object that implements that interface. +In this case, your ``Invoice`` entity has a relationship to the interface +``InvoiceSubjectInterface``. Since interfaces are not valid Doctrine entities, +the goal is to use the ``ResolveTargetEntityListener`` to replace all +references to this interface with a concrete class that implements it. Set up ------ -This article uses the following two basic entities (which are incomplete for -brevity) to explain how to set up and use the ``ResolveTargetEntityListener``. +This article uses two basic (incomplete) entities to demonstrate how to set up +and use the ``ResolveTargetEntityListener``. -A Customer entity:: +A ``Customer`` entity:: // src/Entity/Customer.php namespace App\Entity; @@ -55,7 +56,7 @@ A Customer entity:: // are already implemented in the BaseCustomer } -An Invoice entity:: +An ``Invoice`` entity:: // src/Entity/Invoice.php namespace App\Entity; @@ -63,9 +64,6 @@ An Invoice entity:: use App\Model\InvoiceSubjectInterface; use Doctrine\ORM\Mapping as ORM; - /** - * Represents an Invoice. - */ #[ORM\Entity] #[ORM\Table(name: 'invoice')] class Invoice @@ -74,7 +72,7 @@ An Invoice entity:: protected InvoiceSubjectInterface $subject; } -An InvoiceSubjectInterface:: +The interface representing the subject used in the invoice:: // src/Model/InvoiceSubjectInterface.php namespace App\Model; @@ -94,8 +92,8 @@ An InvoiceSubjectInterface:: public function getName(): string; } -Next, you need to configure the ``resolve_target_entities`` option, which tells the DoctrineBundle -about the replacement: +Now configure the ``resolve_target_entities`` option to tell Doctrine +how to replace the interface with the concrete class: .. configuration-block:: @@ -145,7 +143,6 @@ about the replacement: Final Thoughts -------------- -With the ``ResolveTargetEntityListener``, you are able to decouple your -modules, keeping them usable by themselves, but still being able to -define relationships between different objects. By using this method, -your modules will end up being easier to maintain independently. +Using ``ResolveTargetEntityListener`` allows you to decouple your modules +while still defining relationships between their entities. This makes your +codebase more modular and easier to maintain over time.