Skip to content

[GraphQL] How to create relation objects in mutation? #3420

Closed
@oleg-brizy

Description

@oleg-brizy

I want to create child entities (fields) in the same mutation

mutation {
  createCollectionType (input: {
      title: "Hello world",
      fields: [
        {
          title: "Field 1",
          type: text
        }
      ]
    }
  ) {
    collectionType { id }
  }
}

but I get error

{
  "errors": [
    {
      "debugMessage": "Nested documents for attribute \"fields\" are not allowed. Use IRIs instead.",
    }
  ]
}

I can't and don't want to use IRIs because it will require multiple mutations (server requests).

• Entity/Resource

/**
 * @ApiResource(
 *  graphql={
 *     "create"={
 *         "mutation"=CollectionTypeMutationResolver::class,
 *         "args"={
 *             "title"={"type"="String!"},
 *             "fields"={"type"="[CollectionTypeFieldInput!]"},
 *         },
 *     }
 *   }
 * )
 *
 * @ORM\Entity(...)
 */
class CollectionType
{
    ...

    /**
     * @ORM\OneToMany(targetEntity="CollectionTypeField", mappedBy="collectionType", cascade={"persist", "remove"})
     * @ORM\OrderBy({"priority": "DESC"})
     *
     * @Assert\Valid()
     */
    private $fields;

CollectionTypeMutationResolver is empty (just return).

collectionTypeFieldInput type (not so relevant)

final class CollectionTypeFieldInputType extends InputObjectType implements TypeInterface
{
    public function __construct(array $config = [])
    {
        $config['fields'] = [
            'title' => Type::nonNull(Type::string()),
            'type' => Type::nonNull(MyTypeRegistry::collectionFieldType()),
        ];

        parent::__construct($config);
    }
}

I tried to rename arg to "createFields" to not match entity property, to bypass the "Nested documents are not allowed".

```php
/**
 * @ApiResource(
 *  graphql={
 *     "create"={
 *         "args"={
 *             "createFields"={"type"="[CollectionTypeFieldInput!]"},
 *         },
 *     }
 *   }
 * )
 */

Then in resolver to populate entity fields property from createFields mutation arg

final class CollectionTypeMutationResolver implements MutationResolverInterface
{
    public function __invoke($item, array $context)
    {
        $fields = new ArrayCollection();
        foreach ($context['args']['input']['createFields'] as $fieldArgs) { print_r($fieldArgs);
            $field = new CollectionTypeField();
            $field->setCollectionType($item);
            $field->setTitle($fieldArgs['title']);
            $field->setType($fieldArgs['type']);
            if (isset($fieldArgs['priority'])) {
                $field->setPriority($fieldArgs['priority']);
            }
            if (isset($fieldArgs['required'])) {
                $field->setRequired($fieldArgs['required']);
            }
        }
        $item->setFields($fields);

        return $item;
    }
}

The entity is created but child entities are not validated and not created. Seems like resolver is executed right before save after $item was persisted (I have read the docs but still don't understand when exactly, after/before what stage, the resolver is executed).


How to create a mutation that creates nested relations (one/any level) ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions