Symfony2表单事件侦听器和数据转换器错误无法实例化接口Doctrine \ … \ ObjectManager

我正在研究一种Symfony 2.3表单,该表单要求字段仅在“创建新”模式下可用。

该字段是多对一关系中的链接,我已设法通过使用jQuery AutoComplete来更改下拉列表,以便通过FormEvents::PRE_SET_DATA事件使用,但是要转换的FormEvents::PRE_SUBMIT提供给对象的ID需要Doctrine ObjectManager。 这转为一个接口并抛出‘无法实例化接口Doctrine \ Common \ Persistence \ ObjectManager’
我已经看过以下类似的问题和文档( 表单事件 , 表单事件下拉列表 , 主义数据转换器 , 动态表单修改 )但是接近结束(并且是php和symfony的新手)我希望不要重新写这篇文章。

您可以在我的Event Listener和Data Transformer类下面找到:

 namespace XXXXXXXBundle\Form\EventListener; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\Form\FormEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use XXXXXXXXXXXXXBundle\Form\DataTransformer\rneToEcoleTransformer; class AddFieldSubscriber implements EventSubscriberInterface { private $manager; public static function getSubscribedEvents() { // Tells the dispatcher that you want to listen on the form.pre_set_data // event and that the preSetData method should be called. return array(\Symfony\Component\Form\FormEvents::PRE_SET_DATA => 'preSetData', \Symfony\Component\Form\FormEvents::PRE_SUBMIT => 'preSubmit'); } public function preSetData(\Symfony\Component\Form\FormEvent $event) { $parents = $event->getData(); $form = $event->getForm(); //Verifie si le parent d'eleve est un nouveau //ou s'il s'agit d' une mise à jour if (!$parents || null === $parents->getId()) { $form->add('ecole', 'text', array('invalid_message' => 'Ce RNE n\'est pas valide', 'attr' => array('data-id' => 'ecoles', 'data-url' => 'parents_json_ecoles' ) ) ); } } public function preSubmit(\Symfony\Component\Form\FormEvent $event) { $this->manager = new \Doctrine\Common\Persistence\ObjectManager; $parents = $event->getData(); if (empty($parents['ecole'])) { return; } $event->getForm()->get('ecole')->getConfig()->addModelTransformer(new rneToEcoleTransformer($this->manager)); }} namespace XXXXXXXBundle\Form\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; class rneToEcoleTransformer implements DataTransformerInterface { private $manager; public function __construct(\Doctrine\Common\Persistence\ObjectManager $manager) { $this->manager = $manager; } public function transform($ecole) { if (null === $ecole) { return ''; } return $ecole->getRne(); } public function reverseTransform($rneNumber) { if (!$rneNumber) { return; } $ecole = $this->manager ->getRepository('XXXXXXXBundle:Ecole') ->find($rneNumber); if (null === $ecole) { throw new TransformationFailedException(sprintf( 'No matching data was found "%s" !', $rneNumber )); } return $ecole; }} 

以下是使用的操作:

 private function createCreateForm(Parents $entity) { $manager = $this->getDoctrine()->getManager(); $form = $this->createForm(new ParentsType($manager), $entity, array( 'action' => $this->generateUrl('parents_create'), 'method' => 'POST', )); $form->add('submit', 'submit', array('label' => 'Add')); return $form; } 

表格类型:

 class XXXXType extends AbstractType { private $manager; public function __construct(\Doctrine\Common\Persistence\ObjectManager $manager) { $this->manager = $manager; } /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('nom', 'text', array('label' => 'Nom *', 'attr' => array('placeholder' => 'Nom ', 'maxlength' => 250, 'trim' => true) ) ) ->add('prenoms', 'text', array('label' => 'Prénom(s) *', 'attr' => array('placeholder' => 'Prénom(s)', 'maxlength' => 250, 'trim' => true) ) ) ->add('date_de_naiss', 'date', array('widget' => 'single_text', 'format' => 'dd-MM-yyyy', 'label' => 'Date de naissance ', 'required' => false, 'data' => null, 'attr' => array('name' => 'datepicker') ) ) ->add('telephone', 'text', array('label' => 'Telephone *', 'attr' => array('placeholder' => '123-456-7890 or 1234567890') ) ) ->add('email', 'email', array('attr' => array('placeholder' => 'xxxx@xxxx.com',), 'trim' => true, 'required' => false, 'data' => null ) ); $builder->addEventSubscriber(new AddFieldSubscriber($manager)); } /** * @param OptionsResolverInterface $resolver */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'XXXXXXBundle\Entity\Parents' )); } /** * @return string */ public function getName() { return 'XXXXXXXXXsbundle_parents'; } } 

试试这个:

 class AddFieldSubscriber implements EventSubscriberInterface { private $manager; public function __constructor(ObjectManager $manager){ $this->manager = $manager; } . . . } 

并在您的service.yml定义中:

 : class: XXXXXXXBundle\Form\EventListener\AddFieldSubscriber arguments: ["@doctrine.orm.entity_manager"] tags: - { name: kernel.event_subscriber } 

如果您打算只使用ObjectManager中的一个存储库,我建议只注入此特定存储库。

在这种情况下,您的课程将更改为:

 class AddFieldSubscriber implements EventSubscriberInterface { private $ecoleRepository; public function __constructor(EntityRepository $ecoleRepository){ $this->ecoleRepository = $ecoleRepository; } . . . } 

并在您的service.yml:

 xxx.ecole.repository: class: Doctrine\ORM\EntityRepository factory_service: doctrine.orm.default_entity_manager factory_method: getRepository arguments: - XXXXXXXBundle\Entity\Ecole : class: XXXXXXXBundle\Form\EventListener\AddFieldSubscriber arguments: ["@xxx.ecole.repository"] tags: - { name: kernel.event_subscriber } 

我终于设法使用数据转换器而不是事件订阅者使其工作如下:
`

 class ParentsType extends AbstractType { /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('nom', 'text', array('label' => 'Nom *', 'attr' => array('placeholder' => 'Nom du Parent d\'élève', 'maxlength' => 250, 'trim' => true) ) ) ->add('prenoms', 'text', array('label' => 'Prénom(s) *', 'attr' => array('placeholder' => 'Prénom(s) du parent d\' élève', 'maxlength' => 250, 'trim' => true) ) ) ->add('date_de_naiss', 'date', array('widget' => 'single_text', 'format' => 'dd-MM-yyyy', 'label' => 'Date de naissance ', 'required' => false, 'data' => null, 'attr' => array('name' => 'datepicker') ) ) ->add('telephone', 'text', array('label' => 'Telephone *', 'attr' => array('placeholder' => '123-456-7890 or 1234567890') ) ) ->add('email', 'email', array('attr' => array('placeholder' => 'xxxx@xxxx.com',), 'trim' => true, 'required' => false, 'data' => null ) ); $entityManager = $options['em']; $transformer = new idToEcoleTransformer($entityManager); $builder->add( $builder->create('ecole','text',array('required' => true, 'attr' => array( 'data-id'=>'ecoles', 'data-url'=>'parents_json_ecoles',) ) )->addModelTransformer($transformer) ); } /** * @param OptionsResolverInterface $resolver */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'XXXXXXXXBundle\Entity\Parents', 'csrf_protection' => false, 'validation_groups' => array('filtering') )); $resolver->setRequired(array('em')); $resolver->setAllowedTypes(array('em'=>'Doctrine\Common\Persistence\ObjectManager',)); } /** * @return string */ public function getName() { return 'parentsbundle_parents'; } ` 

有了这个,我不需要通过构造函数传递ObjectManager ,只是使用解析器

Interesting Posts