Hello!
I think my question is common enough and was asked before, but I didnt find something similar.
So, if I have 2 not-doctrine entities:
/**
* ApiResource
*/
class Parent
{
/**
/**
* @ApiProperty(identifier=true)
*
* @var int
*/
public $id;
/**
* @ApiSubresource()
*
* @var Child[]|null
*/
public $childs = [];
}
/**
* @ApiResource
*/
class Child
{
/**
* @ApiProperty(identifier=true)
*
* @var int
*/
public $id;
}
Then in GraphQl schema I see that both of these classes were recognized by SchemaBuilder, but Parent has no proper one-to-many link to Child - childs property has type Iterable instead of Child[].
What am I missing here?
Thanks.
This is a known issue. I will fix it when I have some time.
@alanpoulain thanks for an answer. How do you think, this is only a Schema Builder issue or it's something what involves many different classes and subsystems of ApiP?
If it's only related to Schema Builder, I can try to investigate this myself and create PR.
Hello @Siregacvek,
we had some discussion about this issue in https://github.com/api-platform/core/issues/2687. You ca take a look there, I need to write a Behat test for this
@alanpoulain @Maxell92 looks like I solved my issue (not sure that this will work for @Maxell92 case). The issue is here https://github.com/api-platform/core/blob/be932e901402000adf54fa38e0b741f36474be79/src/GraphQl/Type/SchemaBuilder.php#L369-L386
In my case when field is a collection of not-doctrine objects, the $type->getBuiltinType() returns array type, and code falls to wrong case branch. I did the following:
private function isArrayOfObjects(Type $type): bool
{
return Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType() &&
$type->getCollectionValueType() &&
Type::BUILTIN_TYPE_OBJECT === $type->getCollectionValueType()->getBuiltinType();
}
isCollection method: private function isCollection(Type $type): bool
{
return ($type->isCollection() && Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType()) || $this->isArrayOfObjects($type);
}
case branch for array (quite tricky, don't totally like my implementation but it works):...
case Type::BUILTIN_TYPE_ARRAY:
case Type::BUILTIN_TYPE_ITERABLE:
if (!$this->isArrayOfObjects($type)) {
$graphqlType = $this->graphqlTypes['Iterable'];
break;
}
...
After these changes the schema works fine for me.
But the next problem was that my childs field is empty always. I explored the code and noticed, that there is a CollectionResolver class which handles my case:
https://github.com/api-platform/core/blob/be932e901402000adf54fa38e0b741f36474be79/src/GraphQl/Resolver/Factory/CollectionResolverFactory.php#L86-L89
It delegates fetching collection to src/Bridge/Doctrine/Orm/SubresourceDataProvider.php which of course can't find the items. So I was needed to create my custom implementation of SubresourceDataProviderInterface and it finally works for me.
@alanpoulain please, let me know if I solved the issue in a wrong way.
Should be solved with https://github.com/api-platform/core/pull/3327.
Most helpful comment
Hello @Siregacvek,
we had some discussion about this issue in https://github.com/api-platform/core/issues/2687. You ca take a look there, I need to write a Behat test for this