我会选择一个标准(即:非 Doctrine)选择类型,其中包含一个代表每个 DepartmentType 的选择。
然后使用 DataTransformer 将所选选项转换为相关类型,反之亦然。
您的自定义 FormType 最终应该看起来像这样:
class Department extends AbstractType
{
private $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new DepartmentToTypeTransformer($this->em);
$builder->addViewTransformer($transformer, true);
$builder->getParent()->addEventListener(FormEvents::PRE_BIND, function($event) use ($transformer) {
$data = (object) $event->getData();
$transformer->setDealership($data->dealership);
});
}
public function getParent()
{
return 'choice';
}
public function getName()
{
return 'department';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$choices = array();
foreach ($this->em->getRepository('AcmeDemoBundle:DepartmentType')->findAll() as $type) {
$choices[$type->getId()] = (string) $type;
}
$resolver->setDefaults(array(
'choices' => $choices,
'expanded' => true
));
}
}
请注意将 Dealership 传递到 DataTransformer 以用于转换。
和 DataTransformer 是这样的:
class DepartmentToTypeTransformer implements DataTransformerInterface
{
private $em;
private $dealership;
public function __construct($em)
{
$this->em = $em;
}
public function transform($department)
{
if (null === $department) {
return $department;
}
return $department->getType()->getId();
}
public function reverseTransform($type)
{
if (null === $type) {
return $type;
}
return $this->em->getRepository('AcmeDemoBundle:Department')->findOneBy(array(
'dealership' => $this->getDealership(),
'type' => $type
));
}
public function getDealership() {
return $this->dealership;
}
public function setDealership($dealership) {
$this->dealership = $dealership;
return $this;
}
}
您对传递给转换器的内容的困惑很可能是由于您要绑定的转换器附加到预先存在的行为,请尝试将true
其作为第二个参数添加到 addViewTransformer:
$transformer = new DepartmentToTypeTransformer($this->em);
$builder->addViewTransformer($transformer, true);
从文档:
FormBuilder::addViewTransformer(
DataTransformerInterface $viewTransformer,
Boolean $forcePrepend = false
)
Appends / prepends a transformer to the view transformer chain.