У меня есть три объекта: страна, штат и город со следующими отношениями:
При создании города мне нужны два селектора, один для страны, а другой для штата, которому принадлежит город. Эти два селектора должны быть соединены в цепочку, поэтому изменение страны будет "фильтровать" состояния, показанные в другом селекторе.
Я нашел учебник, показывающий, как это сделать с помощью событий формы, но их пример это не совсем мой случай. Мой объект City не имеет прямого отношения к объекту Country (они косвенно связаны через State), поэтому при установке поля страны в форме City (внутри класса CityType) я вынужден объявить это поле как 'property_path'=>false
как Вы можете увидеть в коде ниже:
class CityType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('country', 'entity', array(
'class'=>'TestBundle:Country',
'property'=>'name',
'property_path'=>false //Country is not directly related to City
));
$builder->add('name');
$factory = $builder->getFormFactory();
$refreshStates = function ($form, $country) use ($factory)
{
$form->add($factory->createNamed('entity', 'state', null, array(
'class' => 'Test\TestBundle\Entity\State',
'property' => 'name',
'query_builder' => function (EntityRepository $repository) use ($country)
{
$qb = $repository->createQueryBuilder('state')
->innerJoin('state.country', 'country');
if($country instanceof Country) {
$qb->where('state.country = :country')
->setParameter('country', $country);
} elseif(is_numeric($country)) {
$qb->where('country.id = :country')
->setParameter('country', $country);
} else {
$qb->where('country.name = :country')
->setParameter('country', "Venezuela");;
}
return $qb;
}
)));
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) use ($refreshStates)
{
$form = $event->getForm();
$data = $event->getData();
if($data == null)
return;
if($data instanceof City){
if($data->getId()) { //An existing City
$refreshStates($form, $data->getState()->getCountry());
}else{ //A new City
$refreshStates($form, null);
}
}
});
$builder->addEventListener(FormEvents::PRE_BIND, function (DataEvent $event) use ($refreshStates)
{
$form = $event->getForm();
$data = $event->getData();
if(array_key_exists('country', $data)) {
$refreshStates($form, $data['country']);
}
});
}
public function getName()
{
return 'city';
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Test\TestBundle\Entity\City');
}
}
Проблема в том, что когда я пытаюсь редактировать существующий Город, связанная Страна не выбирается по умолчанию в форме. Если я удаляю строку 'property_path'=>false
, я получаю (не удивительно) сообщение об ошибке:
Ни свойства "страна", ни метод "getCountry()", ни метод "isCountry()" не существуют в классе "Test\TestBundle\Entity\City"
Есть идеи?