par
ouckileou » 03 mai 2013, 14:41
Voici:
ClassSessionController:
/**
* Displays a form to create a new ClassSession entity.
*
* @Route("/add", name="classsession_new")
* @Route("/add/course/{id}", name="classsession_add")
* @Template()
*/
public function newAction(Course $course) {
$classSession = new ClassSession();
$classSession->setCourse($course);
$organizationBranchId = $this->getSelectedOrganizationBranchId();
$currentTeacher = $this->getConnectedUser();
$semesterId = $this->getSelectedSemesterId();
$form = $this->createForm(new ClassSessionType($this->getDoctrine(), $organizationBranchId, $currentTeacher, $semesterId), $classSession, array('em' => $this->getDoctrine()->getManager()));
return array(
'entity' => $classSession,
'form' => $form->createView(),
'course'=> $course
);
}
/**
* Creates a new ClassSession entity.
*
* @Route("/create", name="classsession_create")
* @Method("POST")
* @Template("VirguleMainBundle:ClassSession:new.html.twig")
*/
public function createAction(Request $request) {
$entity = new ClassSession();
//$form = $this->initClassSessionForm($entity, $courseId);
$organizationBranchId = $this->getSelectedOrganizationBranchId();
$currentTeacher = $this->getConnectedUser();
$form = $this->createForm(new ClassSessionType($this->getDoctrine(), $organizationBranchId, $currentTeacher), $entity, array(
'em' => $this->getDoctrine()->getManager(),
));
$form->bind($request);
$entity->setReportDate(new \Datetime('now'));
$connectedUser = $this->getConnectedUser();
$entity->setReportTeacher($connectedUser);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('classsession_index'));
}
$this->logDebug("Students saved: " . count($entity->getClassSessionStudents()));
foreach ($entity->getClassSessionStudents() as $student) {
$this->logDebug($student->getId());
}
return array(
'course_id' => $courseId,
'course' => $course,
'entity' => $entity,
'form' => $form->createView(),
);
}
ClassSessionType:
<?php
namespace Virgule\Bundle\MainBundle\Form;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Virgule\Bundle\MainBundle\Entity\Teacher;
use Virgule\Bundle\MainBundle\Form\EventListener\AddClassSessionStudentsFieldSubscriber;
use Virgule\Bundle\MainBundle\Form\DataTransformer\CourseToIdTransformer;
class ClassSessionType extends AbstractType {
private $organizationBranchId;
private $doctrine;
private $currentTeacher;
public function __construct(RegistryInterface $doctrine, $organizationBranchId = null, Teacher $currentTeacher = null) {
$this->doctrine = $doctrine;
$this->organizationBranchId = $organizationBranchId;
$this->currentTeacher = $currentTeacher;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$now = new \DateTime('now');
$sNow = $now->format('d/m/Y');
$builder
->add('sessionDate', 'date', array(
'widget' => 'single_text',
'format' => 'dd/MM/yyyy',
'attr' => array('class' => 'date', 'value' => $sNow)))
->add('summary')
->add('sessionTeacher', 'entity', array(
'class' => 'VirguleMainBundle:Teacher',
'query_builder' => $this->getTeachers($this->organizationBranchId),
'multiple' => false,
'expanded' => false,
'property_path' => 'sessionTeacher',
'attr' => array('class' => 'small-select'),
'preferred_choices' => array($this->currentTeacher))
)
->add('course_id', 'hidden', array(
'data' => $data->getCourse()->getId(),
'mapped' => false))
;
// this assumes that the entity manager was passed in as an option
$entityManager = $options['em'];
$transformer = new CourseToIdTransformer($entityManager);
$subscriber = new AddClassSessionStudentsFieldSubscriber($builder->getFormFactory());
$builder->addEventSubscriber($subscriber);
}
private function getTeachers($organizationBranchId) {
$qb = $this->doctrine->getRepository('VirguleMainBundle:Teacher')->getAvailableTeachersQueryBuilder($organizationBranchId);
return $qb;
}
private function getStudents($courseId) {
$qb = $this->doctrine->getRepository('VirguleMainBundle:Student')->getQueryBuilderForStudentEnrolledInCourses(Array($courseId));
return $qb;
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Virgule\Bundle\MainBundle\Entity\ClassSession',
));
$resolver->setRequired(array(
'em',
));
$resolver->setAllowedTypes(array(
'em' => 'Doctrine\Common\Persistence\ObjectManager',
));
}
public function getName() {
return 'virgule_bundle_mainbundle_classsessiontype';
}
}
Dans celui-ci, je ne sais pas comment accéder à l'objet ClassSession passé en paramètre du Form, ici:
$form = $this->createForm(new ClassSessionType($this->getDoctrine(), $organizationBranchId, $currentTeacher, $semesterId), $classSession, array('em' => $this->getDoctrine()->getManager()));
Afin de récupérer l'ID du cours pour mon champ caché.
Et donc le field subscriber:
<?php
namespace Virgule\Bundle\MainBundle\Form\EventListener;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AddClassSessionStudentsFieldSubscriber implements EventSubscriberInterface {
/**
* @var FormFactoryInterface
*/
private $factory;
/**
* @var EntityManager
*/
private $om;
/**
* @param factory FormFactoryInterface
*/
public function __construct(FormFactoryInterface $factory) {
$this->factory = $factory;
}
public static function getSubscribedEvents() {
return array(
FormEvents::PRE_BIND => 'preBind',
FormEvents::PRE_SET_DATA => 'preSetData',
);
}
/**
* @param \Symfony\Component\Form\FormEvent $event
*/
public function preSetData(FormEvent $event) {
/** @var ClassSession $data */
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
//ici ton objet $data fait référence à l'entité ClassSession, ce qui te permet de récupérer la course et son id (vu qu'on a fait l'initialisation dans la méthode newAction avec "$classSession->setCourse($course);")
//je passe par la récup afin de passer la valeur à la fonction anonyme plus bas - ma version de PHP ne gère pas sinon
$courseId = $data->getCourse()->getId();
if ($courseId) {
$field = $this->factory->createNamed('classSessionStudents', 'entity', $data->getCourse()->getId(), array(
'class' => 'VirguleMainBundle:Student',
'query_builder' => function(EntityRepository $er) use ($courseId) {
return $er->createQueryBuilder('s')
->add('orderBy', 's.lastname ASC, s.firstname ASC')
->innerJoin('s.courses', 'c2', 'WITH', 'c2.id = ?1')
->setParameter('1', $courseId);
},
'expanded' => false,
'multiple' => false,
'property_path' => 'classSessionStudents',
'property' => 'fullname'
));
$form->add($field);
$form->add('course_id', 'hidden', array(
'data' => $courseId,
'mapped' => false))
;
}
}
public function preBind(FormEvent $event) {
$data = $event->getData();
}
}
Le field transformer mais que je n'utilise pas encore:
<?php
namespace Virgule\Bundle\MainBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\TaskBundle\Entity\Issue;
/**
* Description of CourseToNumberTransformer
*
* @author guillaume
*/
class CourseToIdTransformer implements DataTransformerInterface {
/**
* @var ObjectManager
*/
private $om;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om) {
$this->om = $om;
}
/**
* Transforms an object (issue) to a string (number).
*
* @param Issue|null $issue
* @return string
*/
public function transform($course) {
if (null === $course) {
return "";
}
return $course->getId();
}
/**
* Transforms a string (id) to an object (course).
*
* @param string $id
*
* @return Course|null
*
* @throws TransformationFailedException if object (course) is not found.
*/
public function reverseTransform($id) {
if (!$id) {
return null;
}
$issue = $this->om
->getRepository('VirguleMainBundle:Course')
->findOneBy(array('id' => $id))
;
if (null === $course) {
throw new TransformationFailedException(sprintf(
'A course with ID "%s" does not exist!', $id
));
}
return $course;
}
}
?>
Donc voilà, de ce que j'ai compris de tes explications, le point de la doc qui se rapporte à mon problème serait celui-là:
http://symfony.com/doc/current/cookbook ... tted-forms
Je me trompe ?
Voici:
ClassSessionController:
[php]
/**
* Displays a form to create a new ClassSession entity.
*
* @Route("/add", name="classsession_new")
* @Route("/add/course/{id}", name="classsession_add")
* @Template()
*/
public function newAction(Course $course) {
$classSession = new ClassSession();
$classSession->setCourse($course);
$organizationBranchId = $this->getSelectedOrganizationBranchId();
$currentTeacher = $this->getConnectedUser();
$semesterId = $this->getSelectedSemesterId();
$form = $this->createForm(new ClassSessionType($this->getDoctrine(), $organizationBranchId, $currentTeacher, $semesterId), $classSession, array('em' => $this->getDoctrine()->getManager()));
return array(
'entity' => $classSession,
'form' => $form->createView(),
'course'=> $course
);
}
/**
* Creates a new ClassSession entity.
*
* @Route("/create", name="classsession_create")
* @Method("POST")
* @Template("VirguleMainBundle:ClassSession:new.html.twig")
*/
public function createAction(Request $request) {
$entity = new ClassSession();
//$form = $this->initClassSessionForm($entity, $courseId);
$organizationBranchId = $this->getSelectedOrganizationBranchId();
$currentTeacher = $this->getConnectedUser();
$form = $this->createForm(new ClassSessionType($this->getDoctrine(), $organizationBranchId, $currentTeacher), $entity, array(
'em' => $this->getDoctrine()->getManager(),
));
$form->bind($request);
$entity->setReportDate(new \Datetime('now'));
$connectedUser = $this->getConnectedUser();
$entity->setReportTeacher($connectedUser);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('classsession_index'));
}
$this->logDebug("Students saved: " . count($entity->getClassSessionStudents()));
foreach ($entity->getClassSessionStudents() as $student) {
$this->logDebug($student->getId());
}
return array(
'course_id' => $courseId,
'course' => $course,
'entity' => $entity,
'form' => $form->createView(),
);
}[/php]
ClassSessionType:
[php]<?php
namespace Virgule\Bundle\MainBundle\Form;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Virgule\Bundle\MainBundle\Entity\Teacher;
use Virgule\Bundle\MainBundle\Form\EventListener\AddClassSessionStudentsFieldSubscriber;
use Virgule\Bundle\MainBundle\Form\DataTransformer\CourseToIdTransformer;
class ClassSessionType extends AbstractType {
private $organizationBranchId;
private $doctrine;
private $currentTeacher;
public function __construct(RegistryInterface $doctrine, $organizationBranchId = null, Teacher $currentTeacher = null) {
$this->doctrine = $doctrine;
$this->organizationBranchId = $organizationBranchId;
$this->currentTeacher = $currentTeacher;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$now = new \DateTime('now');
$sNow = $now->format('d/m/Y');
$builder
->add('sessionDate', 'date', array(
'widget' => 'single_text',
'format' => 'dd/MM/yyyy',
'attr' => array('class' => 'date', 'value' => $sNow)))
->add('summary')
->add('sessionTeacher', 'entity', array(
'class' => 'VirguleMainBundle:Teacher',
'query_builder' => $this->getTeachers($this->organizationBranchId),
'multiple' => false,
'expanded' => false,
'property_path' => 'sessionTeacher',
'attr' => array('class' => 'small-select'),
'preferred_choices' => array($this->currentTeacher))
)
->add('course_id', 'hidden', array(
'data' => $data->getCourse()->getId(),
'mapped' => false))
;
// this assumes that the entity manager was passed in as an option
$entityManager = $options['em'];
$transformer = new CourseToIdTransformer($entityManager);
$subscriber = new AddClassSessionStudentsFieldSubscriber($builder->getFormFactory());
$builder->addEventSubscriber($subscriber);
}
private function getTeachers($organizationBranchId) {
$qb = $this->doctrine->getRepository('VirguleMainBundle:Teacher')->getAvailableTeachersQueryBuilder($organizationBranchId);
return $qb;
}
private function getStudents($courseId) {
$qb = $this->doctrine->getRepository('VirguleMainBundle:Student')->getQueryBuilderForStudentEnrolledInCourses(Array($courseId));
return $qb;
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Virgule\Bundle\MainBundle\Entity\ClassSession',
));
$resolver->setRequired(array(
'em',
));
$resolver->setAllowedTypes(array(
'em' => 'Doctrine\Common\Persistence\ObjectManager',
));
}
public function getName() {
return 'virgule_bundle_mainbundle_classsessiontype';
}
}
[/php]
Dans celui-ci, je ne sais pas comment accéder à l'objet ClassSession passé en paramètre du Form, ici:
[php] $form = $this->createForm(new ClassSessionType($this->getDoctrine(), $organizationBranchId, $currentTeacher, $semesterId), $classSession, array('em' => $this->getDoctrine()->getManager()));[/php]
Afin de récupérer l'ID du cours pour mon champ caché.
Et donc le field subscriber:
[php]<?php
namespace Virgule\Bundle\MainBundle\Form\EventListener;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AddClassSessionStudentsFieldSubscriber implements EventSubscriberInterface {
/**
* @var FormFactoryInterface
*/
private $factory;
/**
* @var EntityManager
*/
private $om;
/**
* @param factory FormFactoryInterface
*/
public function __construct(FormFactoryInterface $factory) {
$this->factory = $factory;
}
public static function getSubscribedEvents() {
return array(
FormEvents::PRE_BIND => 'preBind',
FormEvents::PRE_SET_DATA => 'preSetData',
);
}
/**
* @param \Symfony\Component\Form\FormEvent $event
*/
public function preSetData(FormEvent $event) {
/** @var ClassSession $data */
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
//ici ton objet $data fait référence à l'entité ClassSession, ce qui te permet de récupérer la course et son id (vu qu'on a fait l'initialisation dans la méthode newAction avec "$classSession->setCourse($course);")
//je passe par la récup afin de passer la valeur à la fonction anonyme plus bas - ma version de PHP ne gère pas sinon
$courseId = $data->getCourse()->getId();
if ($courseId) {
$field = $this->factory->createNamed('classSessionStudents', 'entity', $data->getCourse()->getId(), array(
'class' => 'VirguleMainBundle:Student',
'query_builder' => function(EntityRepository $er) use ($courseId) {
return $er->createQueryBuilder('s')
->add('orderBy', 's.lastname ASC, s.firstname ASC')
->innerJoin('s.courses', 'c2', 'WITH', 'c2.id = ?1')
->setParameter('1', $courseId);
},
'expanded' => false,
'multiple' => false,
'property_path' => 'classSessionStudents',
'property' => 'fullname'
));
$form->add($field);
$form->add('course_id', 'hidden', array(
'data' => $courseId,
'mapped' => false))
;
}
}
public function preBind(FormEvent $event) {
$data = $event->getData();
}
}[/php]
Le field transformer mais que je n'utilise pas encore:
[php]<?php
namespace Virgule\Bundle\MainBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\TaskBundle\Entity\Issue;
/**
* Description of CourseToNumberTransformer
*
* @author guillaume
*/
class CourseToIdTransformer implements DataTransformerInterface {
/**
* @var ObjectManager
*/
private $om;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om) {
$this->om = $om;
}
/**
* Transforms an object (issue) to a string (number).
*
* @param Issue|null $issue
* @return string
*/
public function transform($course) {
if (null === $course) {
return "";
}
return $course->getId();
}
/**
* Transforms a string (id) to an object (course).
*
* @param string $id
*
* @return Course|null
*
* @throws TransformationFailedException if object (course) is not found.
*/
public function reverseTransform($id) {
if (!$id) {
return null;
}
$issue = $this->om
->getRepository('VirguleMainBundle:Course')
->findOneBy(array('id' => $id))
;
if (null === $course) {
throw new TransformationFailedException(sprintf(
'A course with ID "%s" does not exist!', $id
));
}
return $course;
}
}
?>
[/php]
Donc voilà, de ce que j'ai compris de tes explications, le point de la doc qui se rapporte à mon problème serait celui-là: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#dynamic-generation-for-submitted-forms
Je me trompe ?