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

Unable to use GraphQL to retrieve linked entities with a non-default name_converter #5723

Closed
pdesgarets opened this issue Aug 5, 2023 · 2 comments · May be fixed by #5754
Closed

Unable to use GraphQL to retrieve linked entities with a non-default name_converter #5723

pdesgarets opened this issue Aug 5, 2023 · 2 comments · May be fixed by #5754
Labels

Comments

@pdesgarets
Copy link

API Platform version(s) affected: 3.1.13 (main branch also affected)

Description
When using a name_converter other than the default one (for instance Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter), GraphQL queries retrieving linked entities affected by this name_converter will fail with an error message.

Example query :

query User {
    user(id: "/users/${userId}") {
        my_entities {
            totalCount
            edges {
                node {
                    id
                    foo
                }
            }
        }
    }
}

Error message :

The class \"App\\Entity\\MyEntity\" cannot be retrieved from \"App\\Entity\\User\".
Complete GraphQL response with stacktrace :
{
    "errors": [
        {
            "message": "The class \"App\\Entity\\MyEntity\" cannot be retrieved from \"App\\Entity\\User\".",
            "locations": [
                {
                    "line": 3,
                    "column": 9
                }
            ],
            "path": [
                "user",
                "my_entities"
            ],
            "extensions": {
                "debugMessage": "The class \"App\\Entity\\MyEntity\" cannot be retrieved from \"App\\Entity\\User\".",
                "file": "/srv/app/vendor/api-platform/core/src/Doctrine/Common/State/LinksHandlerTrait.php",
                "line": 85,
                "trace": [
                    {
                        "file": "/srv/app/vendor/api-platform/core/src/Doctrine/Orm/State/LinksHandlerTrait.php",
                        "line": 37,
                        "call": "ApiPlatform\\Doctrine\\Orm\\State\\CollectionProvider::getLinks('App\\Entity\\MyEntity', instance of ApiPlatform\\Metadata\\GraphQl\\QueryCollection, array(8))"
                    },
                    {
                        "file": "/srv/app/vendor/api-platform/core/src/Doctrine/Orm/State/CollectionProvider.php",
                        "line": 62,
                        "call": "ApiPlatform\\Doctrine\\Orm\\State\\CollectionProvider::handleLinks(instance of Doctrine\\ORM\\QueryBuilder, array(1), instance of ApiPlatform\\Doctrine\\Orm\\Util\\QueryNameGenerator, array(8), 'App\\Entity\\MyEntity', instance of ApiPlatform\\Metadata\\GraphQl\\QueryCollection)"
                    },
                    {
                        "file": "/srv/app/vendor/api-platform/core/src/State/CallableProvider.php",
                        "line": 43,
                        "call": "ApiPlatform\\Doctrine\\Orm\\State\\CollectionProvider::provide(instance of ApiPlatform\\Metadata\\GraphQl\\QueryCollection, array(1), array(8))"
                    },
                    {
                        "file": "/srv/app/vendor/api-platform/core/src/GraphQl/Resolver/Stage/ReadStage.php",
                        "line": 89,
                        "call": "ApiPlatform\\State\\CallableProvider::provide(instance of ApiPlatform\\Metadata\\GraphQl\\QueryCollection, array(1), array(8))"
                    },
                    {
                        "file": "/srv/app/vendor/api-platform/core/src/GraphQl/Resolver/Factory/CollectionResolverFactory.php",
                        "line": 51,
                        "call": "ApiPlatform\\GraphQl\\Resolver\\Stage\\ReadStage::__invoke('App\\Entity\\MyEntity', 'App\\Entity\\User', instance of ApiPlatform\\Metadata\\GraphQl\\QueryCollection, array(6))"
                    },
                    {
                        "file": "/srv/app/vendor/api-platform/core/src/Symfony/GraphQl/Resolver/Factory/DataCollectorResolverFactory.php",
                        "line": 37,
                        "call": "ApiPlatform\\GraphQl\\Resolver\\Factory\\CollectionResolverFactory::ApiPlatform\\GraphQl\\Resolver\\Factory\\{closure}(array(3), array(0), null, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 714,
                        "call": "ApiPlatform\\Symfony\\GraphQl\\Resolver\\Factory\\DataCollectorResolverFactory::ApiPlatform\\Symfony\\GraphQl\\Resolver\\Factory\\{closure}(array(3), array(0), null, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 631,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::resolveFieldValueOrError(instance of GraphQL\\Type\\Definition\\FieldDefinition, instance of GraphQL\\Language\\AST\\FieldNode, instance of Closure, array(3), instance of GraphQL\\Type\\Definition\\ResolveInfo, null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 1317,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::resolveField(GraphQLType: User, array(3), instance of ArrayObject(1), array(2), null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 1256,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::executeFields(GraphQLType: User, array(3), array(1), instance of ArrayObject(1), null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 1210,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::collectAndExecuteSubfields(GraphQLType: User, instance of ArrayObject(1), array(1), array(3), null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 893,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::completeObjectValue(GraphQLType: User, instance of ArrayObject(1), instance of GraphQL\\Type\\Definition\\ResolveInfo, array(1), array(3), null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 753,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::completeValue(GraphQLType: User, instance of ArrayObject(1), instance of GraphQL\\Type\\Definition\\ResolveInfo, array(1), array(3), null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 640,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::completeValueCatchingError(GraphQLType: User, instance of ArrayObject(1), instance of GraphQL\\Type\\Definition\\ResolveInfo, array(1), array(3), null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 1317,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::resolveField(GraphQLType: Query, null, instance of ArrayObject(1), array(1), null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 298,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::executeFields(GraphQLType: Query, null, array(0), instance of ArrayObject(1), null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
                        "line": 237,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::executeOperation(instance of GraphQL\\Language\\AST\\OperationDefinitionNode, null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/Executor/Executor.php",
                        "line": 157,
                        "call": "GraphQL\\Executor\\ReferenceExecutor::doExecute()"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/GraphQL.php",
                        "line": 160,
                        "call": "GraphQL\\Executor\\Executor::promiseToExecute(instance of GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter, instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, null, array(0), null, null)"
                    },
                    {
                        "file": "/srv/app/vendor/webonyx/graphql-php/src/GraphQL.php",
                        "line": 94,
                        "call": "GraphQL\\GraphQL::promiseToExecute(instance of GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter, instance of GraphQL\\Type\\Schema, 'query User {\n    user(id: \"/users/0189c549-0ba5-75b1-ac3b-e1def9ec72ce\") {\n        my_entities {\n            totalCount\n            edges {\n                node {\n                    id\n                    foo\n                }\n            }\n        }\n    }\n}', null, null, array(0), null, null, null)"
                    },
                    {
                        "file": "/srv/app/vendor/api-platform/core/src/GraphQl/Executor.php",
                        "line": 32,
                        "call": "GraphQL\\GraphQL::executeQuery(instance of GraphQL\\Type\\Schema, 'query User {\n    user(id: \"/users/0189c549-0ba5-75b1-ac3b-e1def9ec72ce\") {\n        my_entities {\n            totalCount\n            edges {\n                node {\n                    id\n                    foo\n                }\n            }\n        }\n    }\n}', null, null, array(0), null, null, null)"
                    },
                    {
                        "file": "/srv/app/vendor/api-platform/core/src/GraphQl/Action/EntrypointAction.php",
                        "line": 61,
                        "call": "ApiPlatform\\GraphQl\\Executor::executeQuery(instance of GraphQL\\Type\\Schema, 'query User {\n    user(id: \"/users/0189c549-0ba5-75b1-ac3b-e1def9ec72ce\") {\n        my_entities {\n            totalCount\n            edges {\n                node {\n                    id\n                    foo\n                }\n            }\n        }\n    }\n}', null, null, array(0), null)"
                    },
                    {
                        "file": "/srv/app/vendor/symfony/http-kernel/HttpKernel.php",
                        "line": 163,
                        "call": "ApiPlatform\\GraphQl\\Action\\EntrypointAction::__invoke(instance of Symfony\\Component\\HttpFoundation\\Request)"
                    },
                    {
                        "file": "/srv/app/vendor/symfony/http-kernel/HttpKernel.php",
                        "line": 74,
                        "call": "Symfony\\Component\\HttpKernel\\HttpKernel::handleRaw(instance of Symfony\\Component\\HttpFoundation\\Request, 1)"
                    },
                    {
                        "file": "/srv/app/vendor/symfony/http-kernel/Kernel.php",
                        "line": 184,
                        "call": "Symfony\\Component\\HttpKernel\\HttpKernel::handle(instance of Symfony\\Component\\HttpFoundation\\Request, 1, true)"
                    },
                    {
                        "file": "/srv/app/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php",
                        "line": 35,
                        "call": "Symfony\\Component\\HttpKernel\\Kernel::handle(instance of Symfony\\Component\\HttpFoundation\\Request)"
                    },
                    {
                        "file": "/srv/app/vendor/autoload_runtime.php",
                        "line": 29,
                        "call": "Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner::run()"
                    },
                    {
                        "file": "/srv/app/public/index.php",
                        "line": 5,
                        "function": "require_once('/srv/app/vendor/autoload_runtime.php')"
                    }
                ]
            }
        }
    ],
    "data": {
        "user": {
            "my_entities": null
        }
    }
}

How to reproduce

Reproducer, with a linked entity MyEntity : https://github.com/pdesgarets/api-platform-reproducer/pull/1/files (starting from latest version of https://github.com/api-platform/demo).

docker-compose up -d
docker-compose exec database psql -U app -c 'insert into my_entity select nextval('\''my_entity_id_seq'\''), u.id , '\''bar'\'' from "user" u limit 1;'
userId=$(docker-compose exec database psql -U app -c 'select id from "user"' -t|tr -d ' ')
curl --location 'https://localhost:3443/graphql' \
--header 'Content-Type: application/json' \
--data '{
    "query": "query User {\n    user(id: \"/users/'${userId}'\") {\n        my_entities {\n            totalCount\n            edges {\n                node {\n                    id\n                    foo\n                }\n            }\n        }\n    }\n}"
}' -k

Possible Solution
It seems to be a problem with how the links are created : GraphQL doc tells about my_entities, but the Link shows a $link->getFromProperty()===myEntities. I couldn't understand where the links definitions come from so I could not investigate further.
But maybe the name_converter should be used at some point ?

Additional Context

@stale
Copy link

stale bot commented Oct 4, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 4, 2023
@stale stale bot closed this as completed Oct 12, 2023
@pdesgarets
Copy link
Author

this is not staled

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 a pull request may close this issue.

1 participant