Bonjour à vous;

J'ai essayé de résoudre tout seul ce problème mais je n'y trouve pas la cause, alors je fais appel à vous les pros.

je suis tombé sur symfony2 depuis quelques peu et mon problème ce que lors de la liaison des deux tables construites via doctrine, le champ de relation n'est fournie à la persistence.

En fait, j'ai créer deux entités avec une relation de type OneToMany.
User(n->m)UserInfo,
lors de la persistance en base de donnée, seul le champ user_id devient (NULL) dans la table UserInfo, les autres tables sont bien rempli. la relation n'y est donc pas.

j'ai renseigné le champ infoUser avec la référencement referencedColumnName="id", mais la relation n'y est pas établie.
Pourtant, en appelant doctrine:schema:validate me donne que tout est synchronisé et doctrine:schema:info tout est ok, et si je rajoute un autre attribut la commande doctrine:generate:entities ne change rien alors qu'il ça doit l'être.
je note que ce Bundle est ajouté au appKernel.php
Merci.

Je voici les codes complet.
Voici ce que donne la table:

<?php

namespace BackOffice\UserBundle\Model;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity as Unique;
use BackOffice\UserBundle\Model\UserInformation;
use Doctrine\ORM\Mapping as ORM;

/**
 * User
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="BackOffice\UserBundle\Model\UserRepository")
 * @Unique(fields="username", message="Username already exists, choose one else")
 * @Unique(fields="email", message="Email alread exists, choose one else")
 * @ORM\HasLifecycleCallbacks()
 */
class User implements UserInterface
{
    /**
     * @var integer
     * 
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string

     * @ORM\Column(name="gender", type="string", length=10)
     * 
     */
    private $gender;
    /**
     * @var string
     * @Assert\NotBlank(message="Username Required")
     * @ORM\Column(name="username", type="string", length=255)
     */
    private $username;

    /**
     * @var string
     * @Assert\NotBlank(message="Password Required")
     * @ORM\Column(name="password", type="string", length=255)
     */
    private $password;

    /**
     * @ORM\ManyToMany(targetEntity="BackOffice\UserBundle\Model\Role", inversedBy="user",cascade={"persist","remove"})
     * @ORM\JoinColumn(nullable = false)
     */
    private $roles;

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

    /**
     * @var string
     * @ORM\Column(name="email", type="string", length=255)
     * @Assert\Email(message="Email invalide")
     */
    private $email;
    /**
     * @var date
     * @ORM\Column(name="date_inscription", type="date")
     * @Assert\DateTime()
     */
    private $date_inscription;
    /**
     * @var date
     * @ORM\Column(name="date_update", type="date")
     * @Assert\DateTime()
     */
    private $date_update;

    /**
     * @var UserInformation
     * @ORM\OneToMany(targetEntity="BackOffice\UserBundle\Model\UserInformation", mappedBy="user", cascade={"persist","remove"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $infoUser;

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function setDate(){
        $this->date_inscription = new \DateTime();
        $this->date_update = new \DateTime();
    }
    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

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

        return $this;
    }

    /**
     * Get username
     *
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

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

        return $this;
    }

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

    /**
     * Set salt
     *
     * @param string $salt
     *
     * @return User
     */
    public function setSalt($salt)
    {
        $this->salt = $salt;

        return $this;
    }

    /**
     * Get salt
     *
     * @return string
     */
    public function getSalt()
    {
        return $this->salt;
    }

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

        return $this;
    }

    /**
     * Get email
     *
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }

    public function eraseCredentials() {

    }

    public function getRoles() {
        return $this->roles->toArray();
    }

    /**
     * Set roles
     *
     * @param string $roles
     *
     * @return User
     */
    public function setRoles($roles)
    {
        $this->roles = $roles;

        return $this;
    }
    /**
     * Constructor
     */
    public function __construct()
    {

        $this->salt = sha1(uniqid(null, true));
        $this->infoUser = new \Doctrine\Common\Collections\ArrayCollection();        
        $this->roles = new \Doctrine\Common\Collections\ArrayCollection();

    }

    /**
     * Add role
     *
     * @param \BackOffice\UserBundle\Model\Role $role
     *
     * @return User
     */
    public function addRole(\BackOffice\UserBundle\Model\Role $role)
    {
        $this->roles[] = $role;

        return $this;
    }

    /**
     * Remove role
     *
     * @param \BackOffice\UserBundle\Model\Role $role
     */
    public function removeRole(\BackOffice\UserBundle\Model\Role $role)
    {
        $this->roles->removeElement($role);
    }

    /**
     * Set dateInscription
     *
     * @param \DateTime $dateInscription
     *
     * @return User
     */
    public function setDateInscription($dateInscription)
    {
        $this->date_inscription = $dateInscription;

        return $this;
    }

    /**
     * Get dateInscription
     *
     * @return \DateTime
     */
    public function getDateInscription()
    {
        return $this->date_inscription;
    }

    /**
     * Set gender
     *
     * @param string $gender
     *
     * @return User
     */
    public function setgender($gender)
    {
        $this->gender = $gender;

        return $this;
    }

    /**
     * Get gender
     *
     * @return string
     */
    public function getgender()
    {
        return $this->gender;
    }

    /**
     * Set dateUpdate
     *
     * @param \DateTime $dateUpdate
     *
     * @return User
     */
    public function setDateUpdate($dateUpdate)
    {
        $this->date_update = $dateUpdate;

        return $this;
    }

    /**
     * Get dateUpdate
     *
     * @return \DateTime
     */
    public function getDateUpdate()
    {
        return $this->date_update;
    }

    /**
     * Add infoUser
     *
     * @param \BackOffice\UserBundle\Model\UserInformation $infoUser
     *
     * @return User
     */
    public function addInfoUser(\BackOffice\UserBundle\Model\UserInformation $infoUser)
    {

        $infoUser->setUser($this);
        $this->infoUser[] = $infoUser;

        return $this;
    }

    /**
     * Remove infoUser
     *
     * @param \BackOffice\UserBundle\Model\UserInformation $infoUser
     */
    public function removeInfoUser(\BackOffice\UserBundle\Model\UserInformation $infoUser)
    {
        $this->infoUser->removeElement($infoUser);
    }

    /**
     * Get infoUser
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getInfoUser()
    {
        return $this->infoUser;
    }
}
<?php

namespace BackOffice\UserBundle\Model;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
 * Adresse
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="BackOffice\UserBundle\Model\AdresseRepository")
 */
class UserInformation
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     * @ORM\Column(name="adresse1", type="string", length=255)
     * @Assert\NotBlank(message="adresse1 ne peut pas être vite")
     */
    private $adresse1;

    /**
     * @var string
     * @ORM\Column(name="alt_adresse", type="string", length=255)
     * 
     */
    private $alt_adresse;
    /**
     * @var integer
     * @ORM\Column(name="telephone1", type="integer")
     * @Assert\Regex(message="{{ %string% }} Invalid",pattern="/^\d{6}$/")
     */
    private $telephone1;    
    /**
     * @var integer
     * @ORM\Column(name="telephone2", type="integer")
     * @Assert\Regex(message="{{ %string% }} Invalid",pattern="/^\d{6}$/")
     * @Assert\NotNull(message="{{ %string% }} Invalid")
     */
    private $telephone2;    

    /**
     * @var User
     * @ORM\ManyToOne(targetEntity="BackOffice\UserBundle\Model\User", inversedBy="infoUser", cascade={"persist"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set adresse1
     *
     * @param string $adresse1
     *
     * @return UserInformation
     */
    public function setAdresse1($adresse1)
    {
        $this->adresse1 = $adresse1;

        return $this;
    }

    /**
     * Get adresse1
     *
     * @return string
     */
    public function getAdresse1()
    {
        return $this->adresse1;
    }

    /**
     * Set altAdresse
     *
     * @param string $altAdresse
     *
     * @return UserInformation
     */
    public function setAltAdresse($altAdresse)
    {
        $this->alt_adresse = $altAdresse;

        return $this;
    }

    /**
     * Get altAdresse
     *
     * @return string
     */
    public function getAltAdresse()
    {
        return $this->alt_adresse;
    }

    /**
     * Set telephone1
     *
     * @param integer $telephone1
     *
     * @return UserInformation
     */
    public function setTelephone1($telephone1)
    {
        $this->telephone1 = $telephone1;

        return $this;
    }

    /**
     * Get telephone1
     *
     * @return integer
     */
    public function getTelephone1()
    {
        return $this->telephone1;
    }

    /**
     * Set telephone2
     *
     * @param integer $telephone2
     *
     * @return UserInformation
     */
    public function setTelephone2($telephone2)
    {
        $this->telephone2 = $telephone2;

        return $this;
    }

    /**
     * Get telephone2
     *
     * @return integer
     */
    public function getTelephone2()
    {
        return $this->telephone2;
    }

    /**
     * Set user
     *
     * @param \BackOffice\UserBundle\Model\User $user
     *
     * @return UserInformation
     */
    public function setUser(\BackOffice\UserBundle\Model\User $user = null)
    {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return \BackOffice\UserBundle\Model\User
     */
    public function getUser()
    {
        return $this->user;
    }
}

le formulaire du model User:

<?php

namespace BackOffice\UserBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use BackOffice\UserBundle\Form\UserInformationType;
use BackOffice\UserBundle\Model\RoleRepository;// pour l'affichage du role dans le formulaire

class UserType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('civilite','choice',array('choices'=>array('1'=>'Mr','2'=>'Mme','3'=>'Mle')))                
            ->add('username','text')
            ->add('password','password')
            ->add('email','email')
            ->add('roles','entity',array(
                'required'=>false,'multiple' => true,

                                        'class'         => 'BackOfficeUserBundle:Role',
                                        'property'      => 'role',
                                        'query_builder'  => function(RoleRepository $r){
                                                                return $r->getOrderedRole();
                                                            }
                                       )
                )

            ->add('infoUser','collection', array('label'=>'adresse','type' => new UserInformationType(),'allow_add'=>true,'allow_delete'=>true))
            // ->add('infoUser',new UserInformationType())

        ;
        //$builder->addEventListener(FormEvents::, $listener)
    }

    /**
     * @param OptionsResolverInterface $resolver
     */

    public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'BackOffice\UserBundle\Model\User',
            'cascade_validation' => true,
            'label'=>'Personnal Information'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'user';
    }
}

le formulaire qui représente UserInformation:

<?php

namespace BackOffice\UserBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class UserInformationType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder

            ->add('adresse1','text')
            ->add('alt_adresse','text',array('required'=>false))
            ->add('telephone1')
            ->add('telephone2','integer',array('required'=>false))

        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'BackOffice\UserBundle\Model\UserInformation'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'userAddress';
    }
}

6 réponses


zikou23
Auteur
Réponse acceptée

c'était l'absence du paramètre by_reference => false dans l'option de la collection qui en a été la cause.
Je close ce sujet. merci!

Salut,

Il faudrait que tu montre ton controller voir comment tu gère la validation de ton formulaire.

zikou23
Auteur

le voici:

<?php

namespace BackOffice\UserBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use BackOffice\Form\LoginFormType;
use BackOffice\UserBundle\Entity\User;
use BackOffice\UserBundle\Form\UserType;

class UserController extends Controller
{
    // connexion user
    public function indexAction()
    {   

        // si User deja connecte, on le redirige selon son role
        if($this->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED')){
            if($this->get('security.context')->isGranted('ROLE_ADMIN'))
                return $this->redirectToRoute('front_admin'); 
            else
                return $this->redirectToRoute('front_home');
        }

        if( $this->getRequest()->attributes->has(SecurityContext::AUTHENTICATION_ERROR))
            $oErrors = $this->getRequest()->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
        else{
            $oErrors = $this->get('session')->get(SecurityContext::AUTHENTICATION_ERROR);
            $this->get('session')->remove(SecurityContext::AUTHENTICATION_ERROR);
        }

        $oUser      = new User();
        $oLoginForm = $this->createForm(
                                    new LoginFormType(), $oUser,
                                    array(
                                            'method'=>'POST', 
                                            'action' => $this->generateUrl('checking')                                                                 )
                                       );

        return $this->render(
                            'BackOfficeUserBundle:Default:index.html.twig',
                            array('oUserForm' => $oLoginForm->createView(),
                                  'oErrors'=>$oErrors,
                                   'zUsername' => $this->get('session')->get(SecurityContext::LAST_USERNAME)
                                )
                            );
    }

    public function submitUserAction(User $iUser = null){

        $oUserType = new UserType();

        $oUser =( $iUser == null )? new User(): $iUser ;
        $oUserForm = $this->createForm( $oUserType , $oUser, 
                                  array('method' => 'POST', 'action'=>$this->generateUrl('submit_user'))
                                  );      
        if($this->getRequest()->getMethod() == 'POST'){

            $oUserForm->handleRequest($this->getRequest());

            if($oUserForm->isValid()){

                /**Encodage du mot de passe de User (sha1) **/
                $oFactory = $this->get('security.encoder_factory');
                $oEncoder = $oFactory->getEncoder($oUser);
                $zPassword = $oEncoder->encodePassword($oUser->getPassword(),$oUser->getSalt());
                $oUser->setPassword($zPassword);
                //var_dump($oUser);
                //var_dump($oUser->getInfoUser());
               // return new Response();
                $this->getEntityManager()->persist($oUser);
                $this->addFlash ("notice", "User saved");
                $this->getEntityManager()->flush();

            }
        }
        return $this->render(
                     'BackOfficeUserBundle::userCRUD.html.twig',
                        array(  
                                'oUserForm' => $oUserForm->createView() ,
                                'zTitle'    => 'CRUD_USER/Admin' ,
                                'zAction'    => 'adduser'
                             )
                     );
    }

    public function getEntityManager(){
        return $this->getDoctrine()->getManager();
    }

    public function viewUserAction(User $id = null){

        $toUsers = ($id == null) ?
                $this->getEntityManager()->getRepository('BackOfficeUserBundle:User')->findAll() :
                $id ;

        if(!is_object($toUsers))
            $this->addFlash ("notice", "No user in table");
        return $this->render(
                     'BackOfficeUserBundle::userCRUD.html.twig',
                        array(  
                                'toUsers' => $toUsers ,
                                'zTitle'    => 'CRUD_USER/Admin' ,
                                'zAction'    => 'viewuser'
                             )
                     );        

    }
}
zikou23
Auteur

certes, dans le contrôlleur ça fonctionne bien en faisant $oUser->addInfoUser($infoUser) mais je voudrais automatiser leur relation dans le modèle,

Bonsoir, alors déjà quelques remarques.

public function getEntityManager(){
        return $this->getDoctrine()->getManager();
    }

Devrait être en private. Car tu ne l'utilises que dans le cadre de ton controller.

Je ne sais pas sur quelle version de symfony tu es mais la gestion de fomulaire que tu utilises est dépréciée. Il faut utiliser l'objet Request on utilisant l'injection de dépendance dans ton controller. DOC

Sinon tu peux utiliser la méthode dump() depuis twig ou ton controller car il est plus performant, il remplace le var_dump de php (à partir de la 2.6 si je me souviens bien sinon il faut l'importer).
Tes relations ont l'air correct.

Tu peux nous faire un dump de $oUserForm ainsi que de $oUser ?

zikou23
Auteur

je vois, je vais essayer, après je t'en informerai, en fait, j'utiliser SF 2.7