Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DocumentValueResolver and MapDocument #774

Merged
merged 2 commits into from
Jul 26, 2023

Conversation

franmomu
Copy link
Contributor

@franmomu franmomu commented Jun 29, 2023

Alternative to #773

Since we cannot use EntityValueResolver and MapEntity, this is an alternative to make it work.

The problem is that since Symfony 6.3, because targeted resolvers, MapEntity cannot be used when using ORM + ODM.

Closes #770
Closes #773

@franmomu franmomu added this to the 4.6.0 milestone Jun 29, 2023
@GromNaN
Copy link
Member

GromNaN commented Jun 29, 2023

What is the actual issue that requires a dedicated DocumentValueResolver? In your proposition, this resolver is a proxy to EntityValueResolver and does nothing different.

The #[MapEntity] works as expected in my demo project on Doctrine ODM.
https://github.com/GromNaN/symfony-demo/blob/60eb116cf2b6a0f9acc0bc6591d70f4a4c9f2c69/src/Controller/BlogController.php#L103

Is it to allow using both ORM and ODM in the same project and avoiding the autowiring alias on Doctrine\Persistence\ManagerRegistry: '@doctrine_mongodb' :
https://github.com/GromNaN/symfony-demo/blob/60eb116cf2b6a0f9acc0bc6591d70f4a4c9f2c69/config/services.yaml#L40

@franmomu
Copy link
Contributor Author

Is it to allow using both ORM and ODM in the same project and avoiding the autowiring alias on Doctrine\Persistence\ManagerRegistry: '@doctrine_mongodb' : https://github.com/GromNaN/symfony-demo/blob/60eb116cf2b6a0f9acc0bc6591d70f4a4c9f2c69/config/services.yaml#L40

Exactly, the problem is having both ORM and ODM and since MapEntity is tied to EntityValueResolver by its FQCN I couldn't come up with something better 😞

@GromNaN
Copy link
Member

GromNaN commented Jun 29, 2023

An alternative could be to have a ManagerRegistry aggregator embedding both ORM and ODM implementations that can be used whether it's an entity or a document.

All in all, I find your approach interesting because it avoids having to use "entity" word for "document". And it doesn't require a lot of specific code.

@@ -208,13 +208,5 @@
<service id="doctrine_mongodb.odm.symfony.fixtures.loader" class="Doctrine\Bundle\MongoDBBundle\Loader\SymfonyFixturesLoader" public="false">
<argument type="service" id="service_container" />
</service>

<service id="doctrine_mongodb.odm.entity_value_resolver" class="Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver">
Copy link
Member

@GromNaN GromNaN Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like a breaking change if someone is already using the MapEntity attribute with the ODM. Not a big deal but it must be documented in the UPGRADE file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm not sure about the BC break, these services were added in 4.6.x and never been released, so if someone is using it is because EntityValueResolver was registered as a service manually, in that case I guess it will continue working fine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and never been released

We're fine changing logic given this argument :)

@franmomu franmomu force-pushed the targeted_resolvers branch 3 times, most recently from 9163f3c to 29a9c78 Compare July 1, 2023 12:53
composer.json Outdated
Comment on lines 41 to 43
"symfony/stopwatch": "^5.4|^6.2",
"symfony/validator": "^5.4|^6.2",
Copy link

@boskos-q boskos-q Jul 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"symfony/stopwatch": "^5.4|^6.2",
"symfony/validator": "^5.4|^6.2",
"symfony/stopwatch": "^5.4|^6.3",
"symfony/validator": "^5.4|^6.3",

I don't want to rush ahead of time, but sf 6.2 is supported till the end of July. Maybe to bump version to ^6.3, tho this can also be done later on as well ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the suggestion! but yeah, better to do that in another PR later

@franmomu franmomu requested review from alcaeus, IonBazan and malarzm July 10, 2023 06:50
Copy link
Member

@malarzm malarzm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to have few functional tests here in the bundle? Just so we know that decorating original classes still works

}

That's it! The bundle uses the ``{id}`` from the route to query for the ``Product``
by the ``id`` column. If it's not found, a 404 page is generated.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
by the ``id`` column. If it's not found, a 404 page is generated.
by the ``id`` field. If it's not found, a 404 page is generated.

Fetch Automatically
~~~~~~~~~~~~~~~~~~~

If your route wildcards match properties on your document, then the resolver
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If your route wildcards match properties on your document, then the resolver
If your route wildcards match properties in your document, then the resolver

not 100% about this one, but on sounds weird when translating in my head :)

* Fetch via primary key because {id} is in the route.
*/
#[Route('/product/{id}')]
public function showByPk(Post $post): Response
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MongoDB does not have a primary key concept, should we just say identifier or is there more to itfunctionality-wise?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name still uses Pk part :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, thanks! fixed


``id``
If an ``id`` option is configured and matches a route parameter, then
the resolver will find by the primary key:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
the resolver will find by the primary key:
the resolver will find by the identifier:

I've seen primary key in previous chapter as well, best to check for it globally

``null`` will not be used for the query.

``objectManager``
By default, the ``DocumentValueResolver`` uses the *default*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how this works in ORM but I'd expect passing entity/document to a ManagerRegistry to figure out which object manager should be used by default?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, so the feature works as I've expected it's just the wording that confused me as default is often name of a default OM. How about

Suggested change
By default, the ``DocumentValueResolver`` uses the *default*
By default, the ``DocumentValueResolver`` will choose DocumentManager that has the class registered for it

or maybe we have something better for when we're talking about multiple document managers? We rarely do (or at least did when I was working in such environment) so I'm not sure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to what you suggested, I haven't found any text in the docs, I think it is fine now and more understandable, thanks


``evictCache``
If true, forces Doctrine to always fetch the document from the database
instead of cache.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ODM does not provide native cache solutions, I believe we shouldn't be documenting (or exposing) the functionality for now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right, I've removed the documentation about this and cannot be configured

@franmomu franmomu force-pushed the targeted_resolvers branch 4 times, most recently from ee43b7c to c40ef51 Compare July 23, 2023 18:56
@franmomu franmomu force-pushed the targeted_resolvers branch from c40ef51 to 8a9aba6 Compare July 23, 2023 19:03
Copy link
Member

@malarzm malarzm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for introducing full-blown functional tests! 🎉

xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="doctrine_mongodb.odm.entity_value_resolver" class="Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this and other services use document instead of entity?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the other ones, but not sure about this one since it's for the EntityValueResolver

* Fetch via primary key because {id} is in the route.
*/
#[Route('/product/{id}')]
public function showByPk(Post $post): Response
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name still uses Pk part :)


/**
* @requires PHP 8.0
* @requires function \Symfony\Bridge\Doctrine\Attribute\MapEntity::__construct
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh this is cool, didn't know one can use @requires this way!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@franmomu franmomu force-pushed the targeted_resolvers branch from 8a9aba6 to 481ee19 Compare July 26, 2023 08:36
@franmomu franmomu force-pushed the targeted_resolvers branch from 481ee19 to 0492beb Compare July 26, 2023 12:18
@franmomu franmomu merged commit 294b0fb into doctrine:4.6.x Jul 26, 2023
@franmomu franmomu deleted the targeted_resolvers branch July 26, 2023 13:41
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;

/** @internal */
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why It's marked as @internal if the original EntityValueResolver is not @internal?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @pepeh, in this case we provide the feature of fetching objects from the controller automatically, I decided to mark this class as @internal since to me it was an implementation detail, if we could use the EntityValueResolver, we could remove this class.

Are you using this class directly?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@franmomu there is option to specify value resolver manually
#[ValueResolver(DocumentValueResolver::class)]
https://symfony.com/doc/current/controller/value_resolver.html#managing-value-resolvers
But if class is @internal IDE will show warning

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Leverage pinned resolvers
5 participants