我有一个模型,其中约会对象与Reminder对象具有OneToMany关系。我想在约会表格中嵌入一系列提醒表格。 Appointment对象有一个属性Appointment.Date。 Reminder对象还有一个属性Reminder.Date。
我创建了一个名为“IntervalType”的自定义类型,包含一个“数字”下拉列表和一个用于Reminder.Date输入的“单位”下拉列表。想法是用户选择数字和单位(“1小时”,“2天”等)。
然后,我需要将“2天”转换为Reminder.Date的DateTime值,该值比Appointment.Date提前2天。我试图找出如何使用名为“IntervalToDateTransformer”的自定义DataTransformer执行此操作。我可以将数据转换器添加到Reminder表单或IntervalType输入等,但是如何让变换器知道Reminder的父Appointment.Date是什么?
答案 0 :(得分:0)
起初我认为这是不可能的,因为我之前在这个问题上做过一些研究。我决定尝试一下,然后我开始工作了。基本上我创建了一个自定义表单类型,它有两个字段问题和选项。然后我设法在数据转换类中获得这两个值,它们可以用于转换。这是文件。
Note that the 'option' field is not used, but I did verify
it was accessible from the data transformer.
Also, I could not manage to render the validation messages declared
on the data transform class when transformation fails. I stopped
there, but if you manage to do it let me know.
First FormType
class IssueSelectorType extends AbstractType
{
/**
* @var ObjectManager
*/
private $om;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('number', 'text', array(
// 'mapped' => false
));
$builder->add('option', 'choice', array(
// 'mapped' => false
));
$transformer = new IssueToNumberTransformer($this->om);
$builder->addViewTransformer($transformer);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'invalid_message' => 'The selected issue does not exist',
));
}
public function getName()
{
return 'issue_selector';
}
public function getParent()
{
return 'field';
}
}
数据转换器类:
class IssueToNumberTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $om;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
/**
* Transforms an object (issue) to a array .
*
* @param Issue|null $issue
* @return array
*/
public function transform($issue)
{
if (null === $issue)
{
return array(
'number' => 0,
'option' => 0
);
}
return array(
'number' => $issue->id,
'option' => 0
);
}
/**
* Transforms a array to an object (issue).
*
* @param array $value
* @return Issue|null
* @throws TransformationFailedException if object (issue) is not found.
*/
public function reverseTransform($value)
{
if (null === $value)
{
return null;
}
if (!is_array($value))
{
throw new UnexpectedTypeException($value, 'array');
}
$number = $value['number'] ;
$option = $value['option'] ;
$issue = $this->om
->getRepository('AcmeTransformerBundle:Issue')
->findOneBy(array('id' => $number))
;
if (null === $issue)
{
throw new TransformationFailedException(sprintf(
'An issue with number "%s" does not exist!', $number
));
}
return $issue;
}
}