Salut,

J'ai suivi la doc d'API Platform mais je n'ai malheureusement pas trouvé de réponse probante que ça soit avec la doc ou google

Voici mes entités :

App\Entity\User.php :

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use DateTime;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ApiResource(
 *     normalizationContext={"groups"={"users_read"}}
 * )
 * @UniqueEntity("email")
 * @UniqueEntity("username")
 */
class User implements UserInterface
{
    /**
     * @var int
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     *
     * @Groups({"users_read"})
     */
    private $id;
    /**
     * @ORM\Column(type="string", length=180, unique=true)
     *
     * @Groups({"users_read"})
     *
     * @Assert\NotBlank
     */
    private $username;
    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];
    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     *
     * @Assert\NotBlank
     */
    private $password;
    /**
     * @var string
     * @ORM\Column(type="string", unique=true)
     *
     * @Groups({"users_read"})
     *
     * @Assert\NotBlank
     * @Assert\Email
     */
    private $email;
    /**
     * @var DateTime
     *
     * @ORM\Column(type="date", nullable=true)
     *
     * @Groups({"users_read"})
     *
     * @Assert\Date()
     */
    private $birthday;
    /**
     * @var string
     *
     * @ORM\Column(type="string", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $avatar;
    /**
     * @var bool
     * @ORM\Column(type="boolean", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $verified = false;
    /**
     * @var string
     *
     * @ORM\Column(type="string", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $verificationToken;
    /**
     * @var DateTime
     *
     * @ORM\Column(type="datetime", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $verificationTokenExpiration;
    /**
     * @var string
     *
     * @ORM\Column(type="string", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $resetToken;
    /**
     * @var DateTime
     *
     * @ORM\Column(type="datetime", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $resetTokenExpiration;
    /**
     * @var bool
     *
     * @ORM\Column(type="boolean", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $emailAlert = false;
    /**
     * @var bool
     *
     * @ORM\Column(type="boolean", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $enabled = true;
    /**
     * @var bool
     *
     * @ORM\Column(type="boolean", nullable=true)
     *
     * @Groups({"users_read"})
     */
    private $banned = false;
    /**
     * @var DateTime
     * @Gedmo\Timestampable(on="create")
     * @ORM\Column(type="datetime")
     *
     * @Groups({"users_read"})
     */
    private $createdAt;
    /**
     * @var DateTime
     * @Gedmo\Timestampable(on="update")
     * @ORM\Column(type="datetime")
     *
     * @Groups({"users_read"})
     */
    private $updatedAt;

    /**
     * @ORM\OneToOne(targetEntity="Farm", mappedBy="user", cascade={"persist", "remove"})
     *
     * @Groups({"users_read"})
     */
    private $farm;

    /**
     * @return int|null
     */
    public function getId(): ?int
    {
        return $this->id;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string)$this->username;
    }

    /**
     * @param string $username
     *
     * @return $this
     */
    public function setUsername(string $username): self
    {
        $this->username = $username;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    /**
     * @param array $roles
     *
     * @return $this
     */
    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string)$this->password;
    }

    /**
     * @param string $password
     *
     * @return $this
     */
    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
        // not needed when using the "bcrypt" algorithm in security.yaml
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    /**
     * @return string|null
     */
    public function getEmail(): ?string
    {
        return $this->email;
    }

    /**
     * @param string $email
     *
     * @return $this
     */
    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * @return DateTimeInterface|null
     */
    public function getBirthday(): ?DateTimeInterface
    {
        return $this->birthday;
    }

    /**
     * @param DateTimeInterface|null $birthday
     *
     * @return $this
     */
    public function setBirthday(?DateTimeInterface $birthday): self
    {
        $this->birthday = $birthday;

        return $this;
    }

    /**
     * @return string|null
     */
    public function getAvatar(): ?string
    {
        return $this->avatar;
    }

    /**
     * @param string|null $avatar
     *
     * @return $this
     */
    public function setAvatar(?string $avatar): self
    {
        $this->avatar = $avatar;

        return $this;
    }

    /**
     * @return bool|null
     */
    public function getVerified(): ?bool
    {
        return $this->verified;
    }

    /**
     * @param bool|null $verified
     *
     * @return $this
     */
    public function setVerified(?bool $verified): self
    {
        $this->verified = $verified;

        return $this;
    }

    /**
     * @return string|null
     */
    public function getVerificationToken(): ?string
    {
        return $this->verificationToken;
    }

    /**
     * @param string|null $verificationToken
     *
     * @return $this
     */
    public function setVerificationToken(?string $verificationToken): self
    {
        $this->verificationToken = $verificationToken;

        return $this;
    }

    /**
     * @return DateTimeInterface|null
     */
    public function getVerificationTokenExpiration(): ?DateTimeInterface
    {
        return $this->verificationTokenExpiration;
    }

    /**
     * @param DateTimeInterface|null $verificationTokenExpiration
     *
     * @return $this
     */
    public function setVerificationTokenExpiration(?DateTimeInterface $verificationTokenExpiration): self
    {
        $this->verificationTokenExpiration = $verificationTokenExpiration;

        return $this;
    }

    /**
     * @return string|null
     */
    public function getResetToken(): ?string
    {
        return $this->resetToken;
    }

    /**
     * @param string|null $resetToken
     *
     * @return $this
     */
    public function setResetToken(?string $resetToken): self
    {
        $this->resetToken = $resetToken;

        return $this;
    }

    /**
     * @return DateTimeInterface|null
     */
    public function getResetTokenExpiration(): ?DateTimeInterface
    {
        return $this->resetTokenExpiration;
    }

    /**
     * @param DateTimeInterface|null $resetTokenExpiration
     *
     * @return $this
     */
    public function setResetTokenExpiration(?DateTimeInterface $resetTokenExpiration): self
    {
        $this->resetTokenExpiration = $resetTokenExpiration;

        return $this;
    }

    /**
     * @return bool|null
     */
    public function getEmailAlert(): ?bool
    {
        return $this->emailAlert;
    }

    /**
     * @param bool|null $emailAlert
     *
     * @return $this
     */
    public function setEmailAlert(?bool $emailAlert): self
    {
        $this->emailAlert = $emailAlert;

        return $this;
    }

    /**
     * @return bool|null
     */
    public function getEnabled(): ?bool
    {
        return $this->enabled;
    }

    /**
     * @param bool|null $enabled
     *
     * @return $this
     */
    public function setEnabled(?bool $enabled): self
    {
        $this->enabled = $enabled;

        return $this;
    }

    /**
     * @return bool|null
     */
    public function getBanned(): ?bool
    {
        return $this->banned;
    }

    /**
     * @param bool|null $banned
     *
     * @return $this
     */
    public function setBanned(?bool $banned): self
    {
        $this->banned = $banned;

        return $this;
    }

    /**
     * @return DateTimeInterface|null
     */
    public function getCreatedAt(): ?DateTimeInterface
    {
        return $this->createdAt;
    }

    /**
     * @return DateTimeInterface|null
     */
    public function getUpdatedAt(): ?DateTimeInterface
    {
        return $this->updatedAt;
    }

    /**
     * @return Farm|null
     */
    public function getFarm(): ?Farm
    {
        return $this->farm;
    }

    /**
     * @param Farm $farm
     *
     * @return $this
     */
    public function setFarm(Farm $farm): self
    {
        /** @var Farm farm */
        $this->farm = $farm;

        // set the owning side of the relation if necessary
        if ($farm->getUser() !== $this) {
            $farm->setUser($this);
        }

        return $this;
    }
}

App\Entity\Farm.php

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use DateTime;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ORM\Entity(repositoryClass="App\Repository\FarmRepository")
 * @ApiResource(
 *     normalizationContext={"groups"={"farms_read"}}
 * )
 */
class Farm
{
    /**
     * @var int
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     *
     * @Groups({"users_read", "farms_read"})
     */
    private $id;
    /**
     * @var string
     * @ORM\Column(type="string", length=45)
     *
     * @Groups({"users_read", "farms_read"})
     */
    private $name;
    /**
     * @var string
     * @ORM\Column(type="string", length=45)
     *
     * @Groups({"users_read", "farms_read"})
     */
    private $suffix;
    /**
     * @var float
     * @ORM\Column(type="float")
     *
     * @Groups({"users_read", "farms_read"})
     */
    private $balance;
    /**
     * @var integer
     * @ORM\Column(type="integer")
     *
     * @Groups({"users_read", "farms_read"})
     */
    private $experience;
    /**
     * @var DateTime
     * @Gedmo\Timestampable(on="create")
     * @ORM\Column(type="datetime")
     *
     * @Groups({"users_read", "farms_read"})
     */
    private $createdAt;
    /**
     * @var DateTime
     * @Gedmo\Timestampable(on="update")
     * @ORM\Column(type="datetime")
     *
     * @Groups({"users_read", "farms_read"})
     */
    private $updatedAt;

    /**
     * @ORM\OneToOne(targetEntity="User", inversedBy="farm", cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
     */
    private $user;

    /**
     * @return int|null
     */
    public function getId(): ?int
    {
        return $this->id;
    }

    /**
     * @return string|null
     */
    public function getName(): ?string
    {
        return $this->name;
    }

    /**
     * @param string $name
     *
     * @return $this
     */
    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return string|null
     */
    public function getSuffix(): ?string
    {
        return $this->suffix;
    }

    /**
     * @param string $suffix
     *
     * @return $this
     */
    public function setSuffix(string $suffix): self
    {
        $this->suffix = $suffix;

        return $this;
    }

    /**
     * @return float|null
     */
    public function getBalance(): ?float
    {
        return $this->balance;
    }

    /**
     * @param float $balance
     *
     * @return $this
     */
    public function setBalance(float $balance): self
    {
        $this->balance = $balance;

        return $this;
    }

    /**
     * @return int|null
     */
    public function getExperience(): ?int
    {
        return $this->experience;
    }

    /**
     * @param int $experience
     *
     * @return $this
     */
    public function setExperience(int $experience): self
    {
        $this->experience = $experience;

        return $this;
    }

    /**
     * @return DateTimeInterface|null
     */
    public function getCreatedAt(): ?DateTimeInterface
    {
        return $this->createdAt;
    }

    /**
     * @return DateTimeInterface|null
     */
    public function getUpdatedAt(): ?DateTimeInterface
    {
        return $this->updatedAt;
    }

    /**
     * @return User|null
     */
    public function getUser(): ?User
    {
        return $this->user;
    }

    /**
     * @param User $user
     *
     * @return $this
     */
    public function setUser(User $user): self
    {
        $this->user = $user;

        return $this;
    }
}

Je souhaite savoir comment soumettre les données d'un formulaire qui contient des données de plusieurs entités dont je peux dépendre ?

Par exemple : lors de l'inscription l'utilisateur renseigne ses informations pour se connecter puis dans ce même formulaire il a les données d'un élevage ce qui pourrait donner un json de la sorte :

{
"username": "user",
    "password": "password",
    "email": "user-test@test.fr",
    "farm": {
        "name": "test",
        "suffix": "test"
    }
}

La relation entre l'utilisateur et l'élevage est un OneToOne (un utilisateur n'a qu'un seul élevage).

Mais au moment de la soumission de ma requête, j'ai cette erreur :

Nested documents for attribute \"farm\" are not allowed. Use IRIs instead.

On va me dire : « Eh mais c'est normal, tu demande une chose qui requiert l'IRI de l'utilisateur dans l'élevage ». Or, j'aimerai que lors de l'enregistrement, ne pas avoir à le définir cette info vu que de base je ne la connais pas encore (à moins de faire une requête qui va enregistrer les données de l'utilisateur et attendre le retour de la requête pour enregistrer les données de l'élevage, je trouve ça un peu moche de faire ça et que si une des requête/serveur/autre plante en route ça risque de faire une belle pagaille).
J'aimerai donc que lorsque j'envoie toutes les données du formulaire au moment de l'enregistrement qu'il sache que les infos de l'élevage sont liées à l'utilisateur (un peu comme dans les formulaires dans Symfony il y a des formulaires imbriqués (EntityType ou CollectionType).

D'avance, merci

Aucune réponse