Bonjour à tous
voilà j'ai intégré mon fosuserbundle pour l'adapter à un projet. J'ai entité enseignant qui a les proprieté classe, ecole, qui sont des entités en relation avec lui. puisque tout les éléves crées par un enseignant sont dans la même classe et la même école, je souhaite récupéré ses informations chez l'enseignant pour automatiquement affecté à chaque élève qu'il créé. voici mon code
//EleveController

<?php

namespace App\UserBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use App\UserBundle\Entity\User;
use App\UserBundle\Form\Type\RegistrationFormType;

class EleveController extends Controller
{

    public function createAction(Request $request)
    {
        $user=$this->getUser();
        $affiliation = $user->GetId();
        $classes = $user->GetClasse();
        $ecoles = $user->GetEcole();

        $users = new User();
        $users->setAffiliation($affiliation);
        $users->setClasse($classes); //ca ne marche pas avec cette ligne 
        $users->setEcole($ecole);//ca ne marche pas non plus

        $form = $this->createForm('App\UserBundle\Form\Type\RegistrationFormType', $users);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($users);
            $em->flush();

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

        return $this->render('eleve/new.html.twig', array(
            'users' => $users,
            'form' => $form->createView(),
        ));
    }

//User.php

<?php
namespace App\UserBundle\Entity;

use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
 * @ORM\Entity
 * @ORM\Table(name="utilisateur")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var int
     *
     * @ORM\Column(name="affiliation", type="integer", nullable=true)
     */
    private $affiliation;

    /**
     * @var string
     *
     * @ORM\Column(name="nom", type="string", length=255, nullable=true)
     */
    private $nom;
    /**
     * @ORM\ManyToOne(targetEntity="App\AdminBundle\Entity\Ecole")
     * @ORM\JoinColumn(nullable=false)
     */
    private $ecole;
    /**
     * @ORM\ManyToOne(targetEntity="App\AdminBundle\Entity\Classe")
     * @ORM\JoinColumn(nullable=false)
     */
    private $classe;

    public function __construct()
    {
        parent::__construct();
        // your own logic
    }

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

        return $this;
    }

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

    /**
     * Set ecole
     *
     * @param \App\AdminBundle\Entity\Ecole $ecole
     * @return User
     */
    public function setEcole(\App\AdminBundle\Entity\Ecole $ecole)
    {
        $this->ecole = $ecole;

        return $this;
    }

    /**
     * Get ecole
     *
     * @return \App\AdminBundle\Entity\Ecole 
     */
    public function getEcole()
    {
        return $this->ecole;
    }

    /**
     * Set classe
     *
     * @param \App\AdminBundle\Entity\Classe $classe
     * @return User
     */
    public function setClasse(\App\AdminBundle\Entity\Classe $classe)
    {
        $this->classe = $classe;

        return $this;
    }

    /**
     * Get classe
     *
     * @return \App\AdminBundle\Entity\Classe 
     */
    public function getClasse()
    {
        return $this->classe;
    }

    /**
     * Set affiliation
     *
     * @param integer $affiliation
     * @return User
     */
    public function setAffiliation($affiliation)
    {
        $this->affiliation = $affiliation;

        return $this;
    }

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

Quelqu'un peut-il m'aider?
entre autre comment faire pour rendre le champ email facultatif dans fosuserbundle (nullable=true)?

14 réponses


nico41
Réponse acceptée

tiens moi au jus ;)

Bonjour,

peux tu nous montrer RegistrationFormType stp ?

Bien sur

<?php

namespace App\UserBundle\Form\Type;

use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Util\LegacyFormHelper;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;

class RegistrationFormType extends BaseType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);
        $builder
            ->add('nom')
            ->add('ecole')
            ->add('classe')
            ->add('roles', 'choice', array(
                'choices' => array('ROLE_ELEVE' => 'Eleve',
                                    'ROLE_ENSEIGNANT' => 'Enseignant',
                                    'ROLE_ADMIN' => 'Administrateur')
                                    ,
                'multiple'=>true
            ))
            ->add('enabled', 'checkbox', array('required' => false))
            ->add('email', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\EmailType'), array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle'))
            ->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle'))
            ->add('plainPassword', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\RepeatedType'), array(
                'type' => LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\PasswordType'),
                'options' => array('translation_domain' => 'FOSUserBundle'),
                'first_options' => array('label' => 'form.password'),
                'second_options' => array('label' => 'form.password_confirmation'),
                'invalid_message' => 'fos_user.password.mismatch',
            ))
        ;
    }

    public function getName()
    {
        return 'app_client_registration';
    }
}

A noter que j'ai remove les champs à remplir automatiquement avec une fonction jquery

Pourquoi il y a t-il des champs pour ecole et classe dans RegistrationFormType ?

Parceque j'utilise le même formulaire pour enregistrer les enseignants et les élèves. chez les enseignant , ces champs doivent exister.

Bonjour,

désolé mais qu'entends tu par "ça ne marche pas..." ? Il n'y a pas de valeurs séléctionnées dans ton formulaire pour les champs select ecole et classe ?

Toujours est-il qu'à ta place je découplerai enseignant et élève dans deux entités différentes. Qu'arrivera t-il quand tu aura besoin par exemple d'ajouter une propriété ancienneté "non nullable" à ton enseignant pour, par exemple bidon, calculer son salaire ? tu sera obligé d'attribuer une ancienneté à tes élèves, bizarre non ? Dans l'esprit enseignant et élève n'ont rien à voir. C'est juste un conseil.

salut nico, lorsque je soumet le form j'ai l'erreur

Expected argument of type "App\AdminBundle\Entity\Classe", "NULL" given

t'es tu assuré que $classe = $user->getClasse() n'était pas null ?

public function setClasse(\App\AdminBundle\Entity\Classe $classe)        <=  n'accepte pas la valeur null
    {
        $this->classe = $classe;

        return $this;
    }

et pour le coup $ecoles = $user->GetEcole(); n'était pas null n'ont plus, car alors tu auras le même problème

je pense que tout vient du fait que ton user étend le BaseUser, pour le passage en session ton user est sérializé, par une fonction définie dans BaseUser certainement ( je connais pas bien FosUserBundle, je ne l'utilise jamais) hors par définition BaseUser ne connait rien des relations avec classe et ecole, donc le user sérializé n'a aucune référence des propriétés classe et ecole ce qui fait qu'une fois désérialisé ($user = $this->getUser()) les propriétés ecole et classe sont nulles ... cqfd.
Soit tu redéfinie la méthode de sérialisation pour le stockage en session ce qui serait la meilleurs solution, soit au pire dans ton controller :

// ...
$profId = $this->getUser()->getId();
$prof = $this->getDoctrine()->getRepository(User::class)->find($profId);

$classe = $prof->getClasse();
$ecole = $prof->getEcole();

$eleve = (new User())->setClasse($classe)->setEcole($ecole);
 // ... le reste

Au pire car tu feras une connexion inutile à la base de données, et tu devras ne pas oublier de le faire à chaque fois que nécéssaire.
Dis moi si au moins ce bout de code fonctionne, que cela confirma ou pas le coup de la sérialisation.
Merci

pour confirmation, methodes de serialisation/deserialisation de FOS\UserBundle\Model\User :


// extrait de FOS\UserBundle\Model\User 

    public function serialize()
    {
        return serialize(array(
            $this->password,
            $this->salt,
            $this->usernameCanonical,
            $this->username,
            $this->expired,
            $this->locked,
            $this->credentialsExpired,
            $this->enabled,
            $this->id,
            $this->expiresAt,
            $this->credentialsExpireAt,
            $this->email,
            $this->emailCanonical,
        ));
    }

    public function unserialize($serialized)
    {
        $data = unserialize($serialized);
        // add a few extra elements in the array to ensure that we have enough keys when unserializing
        // older data which does not include all properties.
        $data = array_merge($data, array_fill(0, 2, null));
        list(
            $this->password,
            $this->salt,
            $this->usernameCanonical,
            $this->username,
            $this->expired,
            $this->locked,
            $this->credentialsExpired,
            $this->enabled,
            $this->id,
            $this->expiresAt,
            $this->credentialsExpireAt,
            $this->email,
            $this->emailCanonical
        ) = $data;
    }

il faut redéfinir ces deux fonction dans ta classe user pour y incorporer les propriétés ecole et classe. Attention il faudra que les classes Ecole et Classe soient elle mêmes sérialisable ( = implements \Serializable ) et attention aux références circulaires

//Attention il faudra que les classes Ecole et Classe soient elle mêmes sérialisable ( = implements \Serializable )
je ne comprends pas bien, pouvez vous m'expliquer? je ne suis que débutant

class Ecole implements \Serializable {
    // ... ton code

  public function serialize()
  {
        return serialize([
                $this->id,
                // toutes les propriétés que tu veux garder dans l'objet sérialisé
        ]);
  }
  public function unserialize($serialized)
  {

        list(
        $this->id,
        // ... etc
        ) = unserialize($serialized);
  }

}

même chose à faire pour Classe

Dans ta classe User :

public function serialize()
    {
        return serialize(array(
            $this->password,
            $this->salt,
            $this->usernameCanonical,
            $this->username,
            $this->expired,
            $this->locked,
            $this->credentialsExpired,
            $this->enabled,
            $this->id,
            $this->expiresAt,
            $this->credentialsExpireAt,
            $this->email,
            $this->emailCanonical,

            // ajout de ce qui t'est nécéssaire
            $this->ecole,
            $this->classe,
        ));
    }

    public function unserialize($serialized)
    {
        $data = unserialize($serialized);
        // add a few extra elements in the array to ensure that we have enough keys when unserializing
        // older data which does not include all properties.
        $data = array_merge($data, array_fill(0, 2, null));
        list(
            $this->password,
            $this->salt,
            $this->usernameCanonical,
            $this->username,
            $this->expired,
            $this->locked,
            $this->credentialsExpired,
            $this->enabled,
            $this->id,
            $this->expiresAt,
            $this->credentialsExpireAt,
            $this->email,
            $this->emailCanonical

            // ajout de ce qui t'est nécéssaire
            $this->ecole,
            $this->classe,
        ) = $data;
    }

je te mache le travail, là !!!!

Merci, Nico, je teste ca dès que je suis dispo et je te fais un retour. parfois, même après avoir maché, avaler est difficile pour un débutant :)