iLi*_*ast 11 php events symfony
我正在构建一个Symfony应用程序并使用带有一些jquery/ajax的表单事件来完成整个"州/地区"的事情.我有一个小问题,我使用的格式省 - >城市 - >郊区.现在我可以告诉我的代码很好,但是当执行到达我向"City"选择添加监听器的部分时,它会抛出错误,说明以下内容:
The child with the name "physicalCity" does not exist.
当我尝试向新创建的字段添加事件监听器时,这显然会发生这种情况,从而为事件监听器创建的元素添加事件监听器?
代码的一部分如下......我做错了什么?任何帮助将非常感谢!
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('schoolName')
->add('physicalProvince', 'entity', array(
'mapped' => false,
'class' => 'MY\MainBundle\Entity\Province',
'empty_value' => 'Select a province',
'attr' => array(
'class' => 'province',
'data-show' => 'physical-city',
)
));
/*
* For the physical cities
*/
$physicalCityModifier = function(FormInterface $form, Province $province = null) {
if (null !== $province)
$cities = $province->getCities();
else
$cities = array();
$form->add('physicalCity', 'entity', array(
'mapped' => false,
'class' => 'MY\MainBundle\Entity\City',
'empty_value' => 'Select a province first',
'choices' => $cities,
'attr' => array(
'class' => 'city physical-city',
'data-show' => 'physical-suburb'
)
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event) use ($physicalCityModifier) {
$data = $event->getData();
if (is_object($data->getPhysicalSuburb()))
$province = $data->getPhysicalSuburb()->getCity()->getProvince();
else
$province = null;
$physicalCityModifier($event->getForm(), $province);
}
);
$builder->get('physicalProvince')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($physicalCityModifier) {
$province = $event->getForm()->getData();
$physicalCityModifier($event->getForm()->getParent(), $province);
}
);
/*
* For the physical suburbs
*/
$physicalSuburbModifier = function(FormInterface $form, City $city = null) {
if (null !== $city)
$suburbs = $city->getSuburbs();
else
$suburbs = array();
$form->add('physicalSuburb', null, array(
'choices' => $suburbs,
'empty_value' => 'Select a city first',
'attr' => array(
'class' => 'physical-suburb'
),
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event) use ($physicalSuburbModifier) {
$data = $event->getData();
if (is_object($data->getCity()))
$city = $data->getCity();
else
$city = null;
$physicalSuburbModifier($event->getForm(), $city);
}
);
$builder->get('physicalCity')->addEventListener(
FormEvents::POST_SUBMIT,
function(FormEvent $event) use ($physicalSuburbModifier) {
$city = $event->getForm()->getData();
$physicalSuburbModifier($event->getForm()->getParent(), $city);
}
);
}
Run Code Online (Sandbox Code Playgroud)
iLi*_*ast 17
如果其他人有类似的问题,我最终在每个领域的活动订阅者的帮助下,在这个网站的帮助下(将其翻译为我们中间的那些非西班牙语的人).
基本上,我所做的是为每个字段(包括省)创建一个新的Subscriber类,然后在每个字段中创建一个查询构建器,以使用前面字段中的值填充它们的值.代码如下所示.
AddProvinceFieldSubscriber.php
class AddProvinceFieldSubscriber implements EventSubscriberInterface {
private $factory;
private $fieldName;
private $type;
public function __construct(FormFactoryInterface $factory, $fieldName) {
$this->factory = $factory;
$this->fieldName = $fieldName . 'Province';
$this->type = $fieldName;
}
public static function getSubscribedEvents() {
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::PRE_SUBMIT => 'preSubmit',
);
}
private function addProvinceForm(FormInterface $form, $province) {
$form->add($this->factory->createNamed($this->fieldName, 'entity', $province, array(
'class' => 'MyThing\MainBundle\Entity\Province',
'mapped' => false,
'empty_value' => 'Select a province',
'query_builder' => function (EntityRepository $repository) {
$qb = $repository->createQueryBuilder('p');
return $qb;
},
'auto_initialize' => false,
'attr' => array(
'class' => 'province ' . $this->type .'-province',
'data-show' => $this->type . '-city',
)
)));
}
public function preSetData(FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
if (null === $data)
return;
$fieldName = 'get' . ucwords($this->type) . 'Suburb';
$province = ($data->$fieldName()) ? $data->$fieldName()->getCity()->getProvince() : null;
$this->addProvinceForm($form, $province);
}
public function preSubmit(FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
if (null === $data)
return;
$province = array_key_exists($this->fieldName, $data) ? $data[$this->fieldName] : null;
$this->addProvinceForm($form, $province);
}
}
Run Code Online (Sandbox Code Playgroud)
AddCityFieldSubscriber.php
class AddCityFieldSubscriber implements EventSubscriberInterface {
private $factory;
private $fieldName;
private $provinceName;
private $suburbName;
private $type;
public function __construct(FormFactoryInterface $factory, $fieldName) {
$this->factory = $factory;
$this->fieldName = $fieldName . 'City';
$this->provinceName = $fieldName . 'Province';
$this->suburbName = $fieldName . 'Suburb';
$this->type = $fieldName;
}
public static function getSubscribedEvents() {
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::PRE_SUBMIT => 'preSubmit',
);
}
private function addCityForm(FormInterface $form, $city, $province) {
$form->add($this->factory->createNamed($this->fieldName, 'entity', $city, array(
'class' => 'MyThing\MainBundle\Entity\City',
'empty_value' => 'Select a city',
'mapped' => false,
'query_builder' => function (EntityRepository $repository) use ($province) {
$qb = $repository->createQueryBuilder('c')
->innerJoin('c.province', 'province');
if ($province instanceof Province) {
$qb->where('c.province = :province')
->setParameter('province', $province);
} elseif (is_numeric($province)) {
$qb->where('province.id = :province')
->setParameter('province', $province);
} else {
$qb->where('province.provinceName = :province')
->setParameter('province', null);
}
return $qb;
},
'auto_initialize' => false,
'attr' => array(
'class' => 'city ' . $this->type . '-city',
'data-show' => $this->type . '-suburb',
)
)));
}
public function preSetData(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
$fieldName = 'get' . ucwords($this->suburbName);
$city = ($data->$fieldName()) ? $data->$fieldName()->getCity() : null;
$province = ($city) ? $city->getProvince() : null;
$this->addCityForm($form, $city, $province);
}
public function preSubmit(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data)
return;
$city = array_key_exists($this->fieldName, $data) ? $data[$this->fieldName] : null;
$province = array_key_exists($this->provinceName, $data) ? $data[$this->provinceName] : null;
$this->addCityForm($form, $city, $province);
}
}
Run Code Online (Sandbox Code Playgroud)
最后是AddSuburbFieldSubscriber.php
class AddSuburbFieldSubscriber implements EventSubscriberInterface {
private $factory;
private $fieldName;
private $type;
public function __construct(FormFactoryInterface $factory, $fieldName) {
$this->factory = $factory;
$this->fieldName = $fieldName . 'Suburb';
$this->type = $fieldName;
}
public static function getSubscribedEvents() {
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::PRE_SUBMIT => 'preSubmit',
);
}
private function addSuburbForm(FormInterface $form, $city) {
$form->add($this->factory->createNamed($this->fieldName, 'entity', null, array(
'class' => 'MyThing\MainBundle\Entity\Suburb',
'empty_value' => 'Select a suburb',
'query_builder' => function (EntityRepository $repository) use ($city) {
$qb = $repository->createQueryBuilder('s')
->innerJoin('s.city', 'city');
if ($city instanceof City) {
$qb->where('s.city = :city')
->setParameter('city', $city);
} elseif (is_numeric($city)) {
$qb->where('city.id = :city')
->setParameter('city', $city);
} else {
$qb->where('city.cityName = :city')
->setParameter('city', null);
}
$sql = $qb->getQuery()->getSQL();
return $qb;
},
'auto_initialize' => false,
'attr' => array(
'class' => 'suburb ' . $this->type . '-suburb',
),
)));
}
public function preSetData(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data)
return;
$fieldName = 'get' . ucwords($this->fieldName);
$city = ($data->$fieldName()) ? $data->$fieldName()->getCity() : null;
$this->addSuburbForm($form, $city);
}
public function preSubmit(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data)
return;
$city = array_key_exists($this->type . 'City', $data) ? $data[$this->type . 'City'] : null;
$this->addSuburbForm($form, $city);
}
}
Run Code Online (Sandbox Code Playgroud)
我不得不在那里添加一些额外的东西,但你得到了它的要点.
在我的表单类型中,我只需添加以下内容:
$builder
->addEventSubscriber(new AddProvinceFieldSubscriber($factory, 'postal'))
->addEventSubscriber(new AddCityFieldSubscriber($factory, 'postal'))
->addEventSubscriber(new AddSuburbFieldSubscriber($factory, 'postal'))
//...
Run Code Online (Sandbox Code Playgroud)
和快乐的日子!希望这有助于某人.
另外,我添加了data-show属性来简化我的AJAX过程,以防万一有人在想.