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

Rework of Doctrine ItemDataProvider #458

Closed

Conversation

theofidry
Copy link
Contributor

@theofidry theofidry commented Mar 12, 2016

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? no
Fixed tickets #457
License MIT
Doc PR none

The objective of this PR is to:

}

if ($resourceManager instanceof EntityManagerInterface) {
// TODO: check if $resourceClass is good here
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO to be checked: @dunglas you're probably more familiar than me on that one

Copy link
Contributor Author

Choose a reason for hiding this comment

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

could also check against the method, not sure

@theofidry
Copy link
Contributor Author

In blocked state:

{
$repository = $resourceManager->getRepository($resourceClass);

if ($repository instanceof EntityRepository) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dunglas should I check against EntityRepository or try if it has the createQueryBuilder() method?

Copy link
Member

Choose a reason for hiding this comment

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

Prefer class_exists it will allow custom implementations to work too.

@theofidry theofidry force-pushed the doctrine-item-provider branch 3 times, most recently from 24d1fbc to 2239a39 Compare March 19, 2016 13:03
@theofidry
Copy link
Contributor Author

ping @dunglas updated the querybuilder part, tell me if it's good for you and I'll add unit tests afterwards

@soyuka
Copy link
Member

soyuka commented Mar 23, 2016

@theofidry I made a use case that broke in v1 due to composite identifiers, feel free to use the behat test case I wrote :).

@theofidry
Copy link
Contributor Author

@soyuka neat, will look into it as soon as I can :)

* @return \Doctrine\ORM\QueryBuilder
*/
private function retrieveQueryBuilder(ObjectManager $resourceManager, string $resourceClass)
{
$repository = $resourceManager->getRepository($resourceClass);

if ($repository instanceof EntityRepository) {
if ($repository instanceof EntityRepository) {
return $repository->createQueryBuilder('o');
}

if ($resourceManager instanceof EntityManagerInterface) {
Copy link
Member

Choose a reason for hiding this comment

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

Can't you add an or condition to avoid code duplication below? (same goes for the repository method_exists).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not really because the order matter here:

  • try with an EntityRepository: optimal case
  • try with a EntityManagerInterface: other optimal case, but requires to do things differently
  • fallback to check if the repository still have this createQueryBuilder() method, and assumes it's the right one (technically there is no guarantee here)
  • last fallback with the manager before throwing an error

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 find this hack pretty ugly but maybe I missed something, it's been some time since I used Doctrine, would be happy to find a better solution

Copy link
Member

Choose a reason for hiding this comment

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

Hmm I don't understand why EntityManagerInterface would take priority upon EntityRepository if it has a createQueryBuilder method.

        if ($repository instanceof EntityRepository || method_exists($repository, 'createQueryBuilder')) {
            return $repository->createQueryBuilder('o');
        }

        if ($resourceManager instanceof EntityManagerInterface || method_exists($resourceManager, 'createQueryBuilder')) {
            return $resourceManager->createQueryBuilder()
                ->select('o')
                ->from($resourceClass, 'o');
        }

        throw new RuntimeException();

I'd add that I find it weird to test that the $resourceManager has the createQueryBuilder, especially if it's not implementing the EntityManagerInterface. IMO this will almost always be false, what's the edge case that I'm missing?

IMO there is no better way of returning a query builder with a select clause on the correct entity, and it's a fine way of doing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm I don't understand why EntityManagerInterface would take priority upon EntityRepository if it has a createQueryBuilder method.

My thinking was trying to get the most reliable solution first, assuming that the EntityReopsitory::createQueryBuilder() is right is a baseless assumption with no means to check if it's true. At least with the EntityManagerInterface it's guaranteed to work.

I'd add that I find it weird to test that the $resourceManager has the createQueryBuilder, especially if it's not implementing the EntityManagerInterface. IMO this will almost always be false, what's the edge case that I'm missing?

$resourceManager could simply be a ObjectManager right?

IMO there is no better way of returning a query builder with a select clause on the correct entity, and it's a fine way of doing it.

I don't have any strong feeling on this, but if you and the others find it better I would be happy to switch to that instead

Copy link
Member

Choose a reason for hiding this comment

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

$resourceManager could simply be a ObjectManager right?

Indeed, and the ObjectManager doesn't provide the createQueryBuilder method. EntityManagerInterface extends ObjectManager, and the createQueryBuilder method belongs to the EntityManagerInterface.

As I'm no Doctrine expert, I've no further opinion on this. Hope others will :).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, we got someone who wrote a book on it right @dunglas?

Copy link
Member

@soyuka soyuka Apr 15, 2016

Choose a reason for hiding this comment

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

I've read one more time and it does make sense in some way :). Does this patch also applies to the CollectionDataProvider?

@theofidry
Copy link
Contributor Author

ping @dunglas

@theofidry
Copy link
Contributor Author

@api-platform/core-team there is one last point for which I'm not sure of the behaviour we should adopt, see the discussion with soyuka. Could you check that so that I fix this and rebase this PR?

@theofidry
Copy link
Contributor Author

ping @api-platform/core-team: there is just one part left, could you guys check it please?


/**
* @param ManagerRegistry $managerRegistry
* @param PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory
* @param PropertyMetadataFactoryInterface $propertyMetadataFactory
* @param QueryItemExtensionInterface[] $itemExtensions
* @param ItemDataProviderInterface|null $decorated
* @param ItemDataProviderInterface|null $decoratedProvider
Copy link
Member

Choose a reason for hiding this comment

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

We're naming this decorated in every other class, why change it here?

@theofidry theofidry changed the title WIP ~ Rework of Doctrine ItemDataProvider Rework of Doctrine ItemDataProvider Apr 23, 2016
@theofidry
Copy link
Contributor Author

Updated

@theofidry
Copy link
Contributor Author

@dunglas is that still relevant? i.e. is it still worth to rebase it?

@dunglas
Copy link
Member

dunglas commented Aug 19, 2016

@theofidry Honestly I don't know. WDYT?

@theofidry
Copy link
Contributor Author

Let me check it when I'm back in London (Tuesday), any opinion before that
would not be very reasonable ^^

On Saturday, 20 August 2016, Kévin Dunglas notifications@github.com wrote:

@theofidry https://github.com/theofidry Honestly I don't know. WDYT?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#458 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AE76gUkGQ0wTou3A4AmCM6pAZlMB-QF5ks5qhi_cgaJpZM4HvaKr
.

@soyuka
Copy link
Member

soyuka commented Sep 30, 2016

Maybe we can close this one?

@theofidry
Copy link
Contributor Author

I don't really have time to take a look at it again so yeah let's do that. The problem may not be solved but I don't see any API change so that's something that could easily come as a patch if a problem were to occur.

@theofidry theofidry closed this Sep 30, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants