relation entre entité symfony4

Ce sujet est résolu
Default
,

Bonjour,

j'ai fait une relation entre les entité user et description mis à jour mes tables depuis la console
donc lors d'une nouvelle inscription si j'ai bien compris les deux tables devrais se remplir enfin la table description avec au moins user_id de renseigner

mais j'ai juste la table user qui se rempli
voici mon code user

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @UniqueEntity(
 *     fields = {"username"},
 *     message = "Ce pseudo est déjà utilisé!"
 * )
 * @UniqueEntity(
 *     fields= {"email"},
 *     message= "Cet email es déjà utilisé!",
 * )
 */
class User implements UserInterface
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\Email(
     *     message = "Veuillez renseigner une adresse email valide!"
     * )
     */
    private $email;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\Length(min="5", minMessage="Mot de passe trop court! (Minimum 5 caractères)")
     */
    private $username;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\Length(min="8", minMessage="Mot de passe trop court! (Minimum 8 caractères)")
     */
    private $password;

    /**
     * @Assert\EqualTo(propertyPath="password", message="Les deux mots de passe ne sont pas identiques!")
     */

    public $confirm_password;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $sexe;


    /**
     *
     * @ORM\OneToMany(targetEntity="App\Entity\Description", mappedBy="user")
     */
    private $description;

    // ...

    public function __construct() {
        $this->description = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    public function getUsername(): ?string
    {
        return $this->username;
    }

    public function setUsername(string $username): self
    {
        $this->username = $username;

        return $this;
    }

    public function getPassword(): ?string
    {
        return $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    public function getSexe(): ?string
    {
        return $this->sexe;
    }

    public function setSexe(string $sexe): self
    {
        $this->sexe = $sexe;

        return $this;
    }

    public function eraseCredentials()
    {
    }
    public function getSalt()
    {
    }
    public function getRoles()
    {
        return ['ROLE_USER'];
    }
}

et description

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\DescriptionRepository")
 */
class Description
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="integer")
     */
    private $user_id;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $naissance_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $naissance_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $yeux_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $yeux_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $cheveux_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $cheveux_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $taille_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $taille_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $poids_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $poids_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $silhouette_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $silhouette_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $profession_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $profession_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $fumeur_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $fumeur_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $origine_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $origine_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $sexualite_lui;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $sexualite_elle;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $statut;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $enfant;

    /**
     * Les adresses sont liées à un client
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="description")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    private $user;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getUserId(): ?int
    {
        return $this->user_id;
    }

    public function setUserId(int $user_id): self
    {
        $this->user_id = $user_id;

        return $this;
    }

    public function getNaissanceLui(): ?string
    {
        return $this->naissance_lui;
    }

    public function setNaissanceLui(?string $naissance_lui): self
    {
        $this->naissance_lui = $naissance_lui;

        return $this;
    }

    public function getNaissanceElle(): ?string
    {
        return $this->naissance_elle;
    }

    public function setNaissanceElle(?string $naissance_elle): self
    {
        $this->naissance_elle = $naissance_elle;

        return $this;
    }

    public function getYeuxLui(): ?string
    {
        return $this->yeux_lui;
    }

    public function setYeuxLui(?string $yeux_lui): self
    {
        $this->yeux_lui = $yeux_lui;

        return $this;
    }

    public function getYeuxElle(): ?string
    {
        return $this->yeux_elle;
    }

    public function setYeuxElle(?string $yeux_elle): self
    {
        $this->yeux_elle = $yeux_elle;

        return $this;
    }

    public function getCheveuxLui(): ?string
    {
        return $this->cheveux_lui;
    }

    public function setCheveuxLui(?string $cheveux_lui): self
    {
        $this->cheveux_lui = $cheveux_lui;

        return $this;
    }

    public function getCheveuxElle(): ?string
    {
        return $this->cheveux_elle;
    }

    public function setCheveuxElle(?string $cheveux_elle): self
    {
        $this->cheveux_elle = $cheveux_elle;

        return $this;
    }

    public function getTailleLui(): ?string
    {
        return $this->taille_lui;
    }

    public function setTailleLui(?string $taille_lui): self
    {
        $this->taille_lui = $taille_lui;

        return $this;
    }

    public function getTailleElle(): ?string
    {
        return $this->taille_elle;
    }

    public function setTailleElle(?string $taille_elle): self
    {
        $this->taille_elle = $taille_elle;

        return $this;
    }

    public function getPoidsLui(): ?string
    {
        return $this->poids_lui;
    }

    public function setPoidsLui(?string $poids_lui): self
    {
        $this->poids_lui = $poids_lui;

        return $this;
    }

    public function getPoidsElle(): ?string
    {
        return $this->poids_elle;
    }

    public function setPoidsElle(?string $poids_elle): self
    {
        $this->poids_elle = $poids_elle;

        return $this;
    }

    public function getSilhouetteLui(): ?string
    {
        return $this->silhouette_lui;
    }

    public function setSilhouetteLui(?string $silhouette_lui): self
    {
        $this->silhouette_lui = $silhouette_lui;

        return $this;
    }

    public function getSilhouetteElle(): ?string
    {
        return $this->silhouette_elle;
    }

    public function setSilhouetteElle(?string $silhouette_elle): self
    {
        $this->silhouette_elle = $silhouette_elle;

        return $this;
    }

    public function getProfessionLui(): ?string
    {
        return $this->profession_lui;
    }

    public function setProfessionLui(?string $profession_lui): self
    {
        $this->profession_lui = $profession_lui;

        return $this;
    }

    public function getProfessionElle(): ?string
    {
        return $this->profession_elle;
    }

    public function setProfessionElle(?string $profession_elle): self
    {
        $this->profession_elle = $profession_elle;

        return $this;
    }

    public function getFumeurLui(): ?string
    {
        return $this->fumeur_lui;
    }

    public function setFumeurLui(?string $fumeur_lui): self
    {
        $this->fumeur_lui = $fumeur_lui;

        return $this;
    }

    public function getFumeurElle(): ?string
    {
        return $this->fumeur_elle;
    }

    public function setFumeurElle(?string $fumeur_elle): self
    {
        $this->fumeur_elle = $fumeur_elle;

        return $this;
    }

    public function getOrigineLui(): ?string
    {
        return $this->origine_lui;
    }

    public function setOrigineLui(?string $origine_lui): self
    {
        $this->origine_lui = $origine_lui;

        return $this;
    }

    public function getOrigineElle(): ?string
    {
        return $this->origine_elle;
    }

    public function setOrigineElle(?string $origine_elle): self
    {
        $this->origine_elle = $origine_elle;

        return $this;
    }

    public function getSexualiteLui(): ?string
    {
        return $this->sexualite_lui;
    }

    public function setSexualiteLui(?string $sexualite_lui): self
    {
        $this->sexualite_lui = $sexualite_lui;

        return $this;
    }

    public function getSexualiteElle(): ?string
    {
        return $this->sexualite_elle;
    }

    public function setSexualiteElle(?string $sexualite_elle): self
    {
        $this->sexualite_elle = $sexualite_elle;

        return $this;
    }

    public function getStatut(): ?string
    {
        return $this->statut;
    }

    public function setStatut(?string $statut): self
    {
        $this->statut = $statut;

        return $this;
    }

    public function getEnfant(): ?string
    {
        return $this->enfant;
    }

    public function setEnfant(?string $enfant): self
    {
        $this->enfant = $enfant;

        return $this;
    }
}

13 Réponse

Default
,

en fait non c'est tout bon c'est moi qui a fait l'erreur dans mon entité Description

j'avais ajouté un user_id donc du coup je l'ai supprimé j'ai regénéré mes entité et du coup c'est tout bon

    public function registration(Request $request, ObjectManager $manager, UserPasswordEncoderInterface $encoder) {
        $description = new Description();
        $user = new User();

        $form = $this->createForm(RegistrationType::class, $user);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $description->setUsername($user->getUsername());
            $hash = $encoder->encodePassword($user, $user->getPassword());
            $user->setPassword($hash);

            $user->setDescription($description);

            $manager->persist($description);
            $manager->persist($user);
            $manager->flush();




            return $this->redirectToRoute('security_login');
        }

        return $this->render('security/registration.html.twig', [
            'form' => $form->createView()
        ]);

    }

Default
,

bon j'ai modifié mon entité User comme cela

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @UniqueEntity(
 *     fields = {"username"},
 *     message = "Ce pseudo est déjà utilisé!"
 * )
 * @UniqueEntity(
 *     fields= {"email"},
 *     message= "Cet email es déjà utilisé!",
 * )
 */
class User implements UserInterface
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\Email(
     *     message = "Veuillez renseigner une adresse email valide!"
     * )
     */
    private $email;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\Length(min="5", minMessage="Mot de passe trop court! (Minimum 5 caractères)")
     */
    private $username;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\Length(min="8", minMessage="Mot de passe trop court! (Minimum 8 caractères)")
     */
    private $password;

    /**
     * @Assert\EqualTo(propertyPath="password", message="Les deux mots de passe ne sont pas identiques!")
     */

    public $confirm_password;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $sexe;

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\Description", cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $description;






    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    public function getUsername(): ?string
    {
        return $this->username;
    }

    public function setUsername(string $username): self
    {
        $this->username = $username;

        return $this;
    }

    public function getPassword(): ?string
    {
        return $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    public function getSexe(): ?string
    {
        return $this->sexe;
    }

    public function setSexe(string $sexe): self
    {
        $this->sexe = $sexe;

        return $this;
    }

    public function eraseCredentials()
    {
    }
    public function getSalt()
    {
    }
    public function getRoles()
    {
        return ['ROLE_USER'];
    }

    public function getDescription(): ?Description
    {
        return $this->description;
    }

    public function setDescription(Description $description): self
    {
        $this->description = $description;

        return $this;
    }
}

et mon SecurityController comme ceci:

public function registration(Request $request, ObjectManager $manager, UserPasswordEncoderInterface $encoder) {
    $user = new User();
    $description = new Description();
    $form = $this->createForm(RegistrationType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $description->setYeuxLui('Bleus');

        $hash = $encoder->encodePassword($user, $user->getPassword());
        $user->setPassword($hash);
        $user->setDescription($description);
        $manager->persist($description);
        $manager->persist($user);
        $manager->flush();



        return $this->redirectToRoute('security_login');
    }

    return $this->render('security/registration.html.twig', [
        'form' => $form->createView()
    ]);

}

je me suis basé sur la doc de symfony ici:

https://symfony.com/doc/current/doctrine/associations.html

mais à la soumission de mon formulaire je rencontre l'erreur suivante:
An exception occurred while executing 'INSERT INTO description (user_id, naissance_lui, naissance_elle, yeux_lui, yeux_elle, cheveux_lui, cheveux_elle, taille_lui, taille_elle, poids_lui, poids_elle, silhouette_lui, silhouette_elle, profession_lui, profession_elle, fumeur_lui, fumeur_elle, origine_lui, origine_elle, sexualite_lui, sexualite_elle, statut, enfant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params [null, null, null, "Bleus", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Le champ 'user_id' ne peut être vide (null)

Default
,

personne n'as une idée du problème?

134298
,

Bonjour,

Il te dit clairement que ton user_id est null et qu'il n'autorise pas les null.
Ton user_id est bien ta clé primaire donc vérifie que dans ta BDD tu l'as bien mis en auto-increment.

Et je ne pense pas que cela change grand chose mais essaye de placer le persist de la description juste au dessus de sont affectation

        $description->setYeuxLui('Bleus');
        $manager->persist($description);
        $hash = $encoder->encodePassword($user, $user->getPassword());
        $user->setPassword($hash);
        $user->setDescription($description);
        $manager->persist($user);
        $manager->flush();
134298
,

Ah non je pense avoir compris ta logique.

Déjà tu devrais faire une relation entre ton entité user et ton entité description du genre OneToOne ou autre je te laisse trouver celle qui correspondra à ton cas de figure.

Ensuite si tu veux affecté un user à une description il faut soit lui affecté un user si tu as une relation

$description ->setUser($user)

Mais dans ton cas sans liaison il faudra que tu donnes l'id de ton user à ta description pour éviter que celui la soit null.

$description->setUserId($user->getId())

Je ne sais pas si tout est bien clair n'hésites pas à me dire si tu as la moindre question

Default
,

ben là du coup je me retrouve avec cette erreur:

Argument 1 passed to App\Entity\Description::setUserId() must be of the type integer, null given, called in G:\Fred\Programmes_files\wamp64\www\rencontre\src\Controller\SecurityController.php on line 31

qui correspond à:
$description->setUserId($user->getId());

par contre d'après la doc je fais du OneToOne car voici ce que dit la doc

There is also a OneToOne relationship (e.g. one User has one Profile and vice versa). In practice, using this is similar to ManyToOne.

c'est pour ça que je suis resté en ManyToOne

134298
,

C'est étrange que tu ais cette erreur ...
Logiquement ton user à forcément un id donc tu affectes cet user id à ta description dans le champ user_id.

Si tu fais un

dump($user)

Qu'est-ce que tu obtiens ?

Default
,

j'ai modifié comme ceci mais pas de dump et toujours la même erreur

    public function registration(Request $request, ObjectManager $manager, UserPasswordEncoderInterface $encoder) {
        $description = new Description();
        $user = new User();

        $form = $this->createForm(RegistrationType::class, $user);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $description->setUserId($user->getId());
            $hash = $encoder->encodePassword($user, $user->getPassword());
            $user->setPassword($hash);

            $user->setDescription($description);

            //$manager->persist($description);
            //$manager->persist($user);
            //$manager->flush();

            dump($user);




            return $this->redirectToRoute('security_login');
        }

        return $this->render('security/registration.html.twig', [
            'form' => $form->createView()
        ]);

    }

Default
,

pourtant je reproduis la meme chose que la doc à la différence c'est que eux lies produits et categorie sur name
et moi user et description sur username

enfin je sais pas si j'ai été clair lol

134298
,

Ah j'ai compris, désolé il me faut toujours deux messages pour me rendre compte de ce qu'il ne vas pas ^^

Alors reprenons.
Dans ta fonction tu créer un formulaire auquel tu joints un new User(), jusque la pas de soucis.

Ensuite quand ton formulaire est validé tu as du coup ton entité user qui à été rempli grâce au formulaire.
Sauf que cette entité n'est pas encore en base de données donc n'a pas encore d'id.

Il faut donc dans un premier temps persister ton user comme ca il aura un user id et ensuite il faudra affecté à ta description l'user id qui vient d'être créer.

Ca nous donnerais quelque chose comme ça :

public function registration(Request $request, ObjectManager $manager, UserPasswordEncoderInterface $encoder) {
    $user = new User();
    $description = new Description();
    $form = $this->createForm(RegistrationType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $description->setYeuxLui('Bleus');
        $manager->persist($description);
        // On créer l''entité description puis on la sauvegarde

        $hash = $encoder->encodePassword($user, $user->getPassword());
        $user->setPassword($hash);
        // On créer le password du User puis on lui affecte

        $user->setDescription($description);
        // On lie la description créer au user

        $manager->persist($user);
        // On sauvegarde le user.

        $manager->flush();
        return $this->redirectToRoute('security_login');
    }

    return $this->render('security/registration.html.twig', [
        'form' => $form->createView()
    ]);

}
Default
,

en attendant je te remercie de t'être penché sur mon problème car depuis ce matin que je galère

134298
,

Content d'avoir pu t'aider ;) et n'oublies pas de passer le sujet en résolut !

Maxime

Default
,

oui oui je le fais de suite

merci encore

@Fred