From 47f81eb6f4bb0c04dc148d2448fc9bc4e252d876 Mon Sep 17 00:00:00 2001 From: NanoSector Date: Mon, 24 Mar 2025 21:31:11 +0100 Subject: [PATCH 1/2] Mention resolve_target_entities support in EntityValueResolver --- doctrine.rst | 22 ++++++++++++++++++++++ doctrine/resolve_target_entity.rst | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/doctrine.rst b/doctrine.rst index 171f8a3348a..9fddb08c7c2 100644 --- a/doctrine.rst +++ b/doctrine.rst @@ -780,6 +780,28 @@ variable. Let's say you want the first or the last comment of a product dependin Comment $comment ): Response { } + +.. _doctrine-entity-value-resolver-resolve-target-entities: + +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:: + + public function show( + #[MapEntity] + ProductInterface $product + ): Response { + // ... + } + +.. versionadded:: 7.3 + + Support for ``resolve_target_entites`` in the ``EntityValueResolver`` was introduced in Symfony 7.3. MapEntity Options ~~~~~~~~~~~~~~~~~ diff --git a/doctrine/resolve_target_entity.rst b/doctrine/resolve_target_entity.rst index 5ae6475a957..3a7497983bf 100644 --- a/doctrine/resolve_target_entity.rst +++ b/doctrine/resolve_target_entity.rst @@ -14,6 +14,11 @@ mappings and expect correct mapping to a concrete entity at runtime. This functionality allows you to define relationships between different entities without making them hard dependencies. +.. tip:: + + Starting with Symfony 7.3, this functionality also works with the ``EntityValueResolver``. + See :ref:`doctrine-entity-value-resolver-resolve-target-entities` for more details. + Background ---------- From 75472f5629e84c32fd8ee21cf79a01b4416c1935 Mon Sep 17 00:00:00 2001 From: NanoSector Date: Mon, 24 Mar 2025 21:31:53 +0100 Subject: [PATCH 2/2] Modernise resolve_target_entities documentation --- doctrine/resolve_target_entity.rst | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/doctrine/resolve_target_entity.rst b/doctrine/resolve_target_entity.rst index 3a7497983bf..c55b27f6463 100644 --- a/doctrine/resolve_target_entity.rst +++ b/doctrine/resolve_target_entity.rst @@ -1,15 +1,15 @@ -How to Define Relationships with Abstract Classes and Interfaces -================================================================ +Referencing Entities with Abstract Classes and Interfaces +========================================================= -One of the goals of bundles is to create discrete bundles of functionality -that do not have many (if any) dependencies, allowing you to use that -functionality in other applications without including unnecessary items. +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. 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 -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. +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 without making them hard dependencies. @@ -22,14 +22,14 @@ without making them hard dependencies. Background ---------- -Suppose you have an InvoiceBundle which provides invoicing functionality -and a CustomerBundle that contains customer management tools. You want -to keep these separated, because they can be used in other systems without -each other, but for your application you want to use them together. +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. -In this case, you have an ``Invoice`` entity with a relationship to a -non-existent object, an ``InvoiceSubjectInterface``. The goal is to get -the ``ResolveTargetEntityListener`` to replace any mention of the interface +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. Set up @@ -94,7 +94,7 @@ An InvoiceSubjectInterface:: public function getName(): string; } -Next, you need to configure the listener, which tells the DoctrineBundle +Next, you need to configure the ``resolve_target_entities`` option, which tells the DoctrineBundle about the replacement: .. configuration-block:: @@ -146,6 +146,6 @@ Final Thoughts -------------- With the ``ResolveTargetEntityListener``, you are able to decouple your -bundles, keeping them usable by themselves, but still being able to +modules, keeping them usable by themselves, but still being able to define relationships between different objects. By using this method, -your bundles will end up being easier to maintain independently. +your modules will end up being easier to maintain independently.