symfony2是否将转换器应用于实体表单字段-空数组?
我正在尝试让dataTransformer处理symfony 2中的实体字段 背景:symfony2是否将转换器应用于实体表单字段-空数组?,symfony,transformer,Symfony,Transformer,我正在尝试让dataTransformer处理symfony 2中的实体字段 背景: 表单显示用户可以选择的帆(复选框) 这是多步骤sail订购流程的第一步(后面的步骤显示每个sail的可用选项、颜色等) 这是我的表单类型类: use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\Form\Fo
- 表单显示用户可以选择的帆(复选框)
- 这是多步骤sail订购流程的第一步(后面的步骤显示每个sail的可用选项、颜色等)
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Co\QuoteBundle\Form\DataTransformer\SailCollectionToStringsTransformer;
class PartsTypeStep1 extends AbstractType {
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Co\QuoteBundle\Entity\Parts',));
$resolver->setRequired(array('sailsAvailable', 'em'));
}
public function buildForm(FormBuilderInterface $formBuilder, array $options)
{
$transformer = new SailCollectionToStringsTransformer($options['em']);
$formBuilder->add(
$formBuilder->create('mainsailparts', 'entity', array(
'class' => 'CoQuoteBundle:Mainsail',
'choices' => $options['sailsAvailable']['mains'],
'multiple' => true,
'expanded' => true,
'label' => 'Mainsails',))
->addModelTransformer($transformer)); //line 58
}
public function getName() {
return 'partsStep1';
}
}
上述操作不会出现错误,但不会显示转换后的数据。意见是:
__ Race main
__ Cruising main
(代表复选框)
然而,我想要的观点是:
__ Race main ($1400)
__ Cruising main ($800)
我拥有的变压器是:
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Co\QuoteBundle\Entity\Sail;
use Doctrine\Common\Collections\ArrayCollection;
class SailCollectionToStringsTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $om;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
/**
* Transforms a collection of sails to a collection of strings.
* @param ISail|null $sail
* @return string
*/
public function transform($sailCollection)
{
if (null === $sailCollection) {
return null;
}
$labels = new ArrayCollection();
foreach($sailCollection as $sail){
$labels[] = $sail->getName().' ($'.$sail->getBuildPrice().')';
}
return $labels;
}
//reverse transformer... not the issue (yet) because the forward transformer doesn't work
}
当通过netbeans调试器运行此命令时,将向转换器传递一个空数组。但是,如果我将第58行更改为addViewTransformer($transformer))代码>和调试,它正确地将两个带有sail id的布尔值作为数组键传递给转换器。不幸的是,我不能使用viewtranformer
,因为它不再包含要更改的原始字符串
为什么应该包含主帆的ArrayCollection作为空ArrayCollection传递给transformer?函数返回一个空的$labels
集合
我不确定我做错了什么。。。非常感谢您的帮助!!!!
谢谢。我从来没有找到一种方法来实现我想做的事情。但是,我使用的解决方法如下所述
对于form type类,我使用了一个form事件,并在控制器的parts对象中保存了boatId(帆对应的),如下所示:
$partsObject = new Parts($boat->getId());
$form = $this->createForm(new PartsTypeStep1(), $partsObject, array(
'em' => $this->getDoctrine()->getManager()));
表单类型类现在如下所示:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Doctrine\ORM\EntityRepository;
class PartsTypeStep1 extends AbstractType {
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Co\QuoteBundle\Entity\Parts',));
$resolver->setRequired(array('em'));
}
public function buildForm(FormBuilderInterface $formBuilder, array $options)
{
$factory = $formBuilder->getFormFactory();
$em = $options['em'];
$formBuilder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event) use($factory, $em){
$form = $event->getForm();
$data = $event->getData();
if (!$data || !$data->getDateTime()) {
return;
}
else {
$boatClass = $data->getBoatId();
$formOptions = array(
'class' => 'CoQuoteBundle:Mainsail',
'multiple' => true,
'expanded' => true,
'property' => 'displayString',
'label' => 'Mainsails',
'query_builder' => function(EntityRepository $er) use ($boatClass) {
return $er->createQueryBuilder('m')
->where('m.boatType = :boatClass')
->setParameter('boatClass', $boatClass);
},
);
$form->add($factory->createNamed('mainsailparts', 'entity', null, $formOptions));
}
}
);
}
public function getName() {
return 'partsStep1';
}
{% if form.mainsailparts|length > 0 %}
<div class="groupHeading">{{ form_label(form.mainsailparts) }}</div>
{% for child in form.mainsailparts %}
{# render each checkbox .... #}
{% endfor %}
{% else %}
{% do form.mainsailparts.setRendered %}
{% endif %}
我还需要在Mainsail
类中添加displayString
属性(我只添加了一个getter,而不是字符串的实际变量)。因此,Mainsail
类现在有:
public function getDisplayString(){
return $this->name . ' - ' . $this->descr . ' ($' . $this->buildPrice . ')';
}
我在这个解决方法中遇到的唯一问题是,如果查询返回一个空结果,会发生什么情况,因为twig将自动呈现表单标签(“Mainsails”),无论它是否有任何要呈现的复选框。我是这样绕过这个问题的:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Doctrine\ORM\EntityRepository;
class PartsTypeStep1 extends AbstractType {
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Co\QuoteBundle\Entity\Parts',));
$resolver->setRequired(array('em'));
}
public function buildForm(FormBuilderInterface $formBuilder, array $options)
{
$factory = $formBuilder->getFormFactory();
$em = $options['em'];
$formBuilder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event) use($factory, $em){
$form = $event->getForm();
$data = $event->getData();
if (!$data || !$data->getDateTime()) {
return;
}
else {
$boatClass = $data->getBoatId();
$formOptions = array(
'class' => 'CoQuoteBundle:Mainsail',
'multiple' => true,
'expanded' => true,
'property' => 'displayString',
'label' => 'Mainsails',
'query_builder' => function(EntityRepository $er) use ($boatClass) {
return $er->createQueryBuilder('m')
->where('m.boatType = :boatClass')
->setParameter('boatClass', $boatClass);
},
);
$form->add($factory->createNamed('mainsailparts', 'entity', null, $formOptions));
}
}
);
}
public function getName() {
return 'partsStep1';
}
{% if form.mainsailparts|length > 0 %}
<div class="groupHeading">{{ form_label(form.mainsailparts) }}</div>
{% for child in form.mainsailparts %}
{# render each checkbox .... #}
{% endfor %}
{% else %}
{% do form.mainsailparts.setRendered %}
{% endif %}
{%if form.mainsailparts | length>0%}
{{form_标签(form.mainsailparts)}
{form.mainsailparts%}
{#呈现每个复选框…}
{%endfor%}
{%else%}
{%do form.mainsailparts.setRendered%}
{%endif%}
我不知道在这种情况下这是否是推荐的解决方案,但它确实可以用于表单验证(如果没有选择sail,至少不允许进行,我不需要任何更严格的操作)
我不打算将此标记为答案,因为它没有回答问题(如何将transformer应用于实体字段),但对于处理相同问题的任何人来说,它都是一个解决方法