[英]Symfony2 Form Events Listener and Data Transformer Error Cannot instantiate interface Doctrine\…\ObjectManager
我正在使用Symfony 2.3表單,該表單要求字段僅在“創建新”模式下可用。
該字段是多對一關系中的鏈接,我設法通過使用jQuery AutoComplete來更改下拉列表,以便通過FormEvents::PRE_SET_DATA
事件輕松使用,但是要轉換的FormEvents::PRE_SUBMIT
提供給對象的ID需要Doctrine ObjectManager。 這將成為一個接口,並拋出“無法實例化接口Doctrine \\ Common \\ Persistence \\ ObjectManager” 。
我看過以下類似的問題和文檔( 表單事件 , 表單事件下拉列表 , Doctrine數據轉換器 , 動態表單修改 ),但已經接近尾聲了(並且是php和symfony的新手),我希望不再重復寫這塊。
可以在我的事件監聽器和數據轉換器類下面找到:
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定義中:
<service_name>:
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
<service_name>:
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 ,而只是使用Resolver
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.