我有一个Symfony 2应用程序,其表单需要在隐藏字段中存储对另一个实体(项目)的引用。项目实体是通过表单选项传递的,我的计划是要有一个隐藏式'它只包含实体id,然后在提交表单时将其转换为项目实体。
我通过使用模型转换器将实体转换为字符串(它的ID)来解决这个问题。但是,当我尝试查看表单时,出现以下错误:
表单的视图数据应该是类Foo \ BarBundle \ Entity \ Project的实例,但是是(n)字符串。您可以通过设置" data_class"来避免此错误。 null的选项或添加视图转换器,将(n)字符串转换为Foo \ BarBundle \ Entity \ Project的实例。
这是我的表单类:
<?php
namespace Foo\BarBundle\Form\SED\Waste;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Foo\BarBundle\Form\DataTransformer\EntityToEntityIdTransformer;
/**
* Class WasteContractorEntryType
* @package Foo\BarBundle\Form\CommunityInvestment\Base
*/
class WasteContractorEntryType extends AbstractType
{
protected $name;
protected $type;
protected $phase;
protected $wasteComponent;
public function __construct($formName, $type, $phase, $wasteComponent)
{
$this->name = $formName;
$this->type = $type;
$this->phase = $phase;
$this->wasteComponent = $wasteComponent;
}
/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* @return mixed
*/
public function getPhase()
{
return $this->phase;
}
/**
* @return mixed
*/
public function getProject()
{
return $this->project;
}
/**
* @return mixed
*/
public function getWasteComponent()
{
return $this->wasteComponent;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$em = $options['em'];
$wasteComponentTransformer = new EntityToEntityIdTransformer($em,
'Foo\BarBundle\Entity\SED\Waste\WasteComponent');
$projectTransformer = new EntityToEntityIdTransformer($em, 'Foo\BarBundle\Entity\Project');
$builder->add('id', 'hidden');
$builder->add(
$builder->create('project', 'hidden', array(
'data' => $options['project'],
'by_reference' => false
))
->addModelTransformer($projectTransformer)
);
$builder->add(
$builder->create('wasteComponent', 'hidden', array(
'data' => $this->getWasteComponent()
))
->addModelTransformer($wasteComponentTransformer)
);
$builder->add('phase', 'hidden', array(
'data' => $this->getPhase()
));
$builder->add('type', 'hidden', array(
'data' => $this->getType()
));
$builder->add('percentDivertedFromLandfill', 'text', array());
$builder->add('wasteContractor', 'entity', array(
'class' => 'Foo\BazBundle\Entity\Contractor',
'property' => 'name',
'attr' => array(
'class' => 'js-select2'
)
));
}
public function getName()
{
return $this->name;
}
/**
* {@inheritDoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => true,
'data_class' => 'Foo\BarBundle\Entity\SED\Waste\WasteContractorEntry'
))
->setRequired(array(
'em',
'project'
))
->setAllowedTypes(array(
'em' => 'Doctrine\Common\Persistence\ObjectManager',
'project' => 'Foo\BarBundle\Entity\Project'
));
}
}
我的模型变换器类:
<?php
namespace Foo\BarBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
class EntityToEntityIdTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $om;
/**
* @var Entity class
*/
protected $entityClass;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om, $className)
{
$this->om = $om;
$this->entityClass = $className;
}
protected function getEntityClass()
{
return $this->entityClass;
}
/**
* Transforms an object (project) to a string (id).
*
* @param Project|null $issue
* @return string
*/
public function transform($entity)
{
if (null === $entity) {
return "";
}
return $entity->getId();
}
/**
* Transforms a string (id) to an object (project).
*
* @param string $id
*
* @return Issue|null
*
* @throws TransformationFailedException if object (project) is not found.
*/
public function reverseTransform($id)
{
if (!$id) {
return null;
}
$entity = $this->om
->getRepository($this->getEntityClass())
->find($id);
if (null === $entity) {
throw new TransformationFailedException(sprintf(
'An entity of class %s with id "%s" does not exist!',
$this->getEntityClass(),
$id
));
}
return $entity;
}
}
我尝试使用添加变压器作为视图变换器而不是模型变换器,但是我只是得到了一个稍微不同的错误:
表单的视图数据应该是类的实例 Foo \ BarBundle \ Entity \ Project,但是是(n)整数。你可以避免这种情况 设置&#34; data_class&#34; null的选项或添加视图的选项 将(n)整数转换为实例的变换器 FOO \ BarBundle \实体\项目。
答案 0 :(得分:0)
似乎将上述异常消息建议的'data_class'设置为null是解决方案。我之前拒绝了这一点,因为当我们知道该领域的目的是引用项目实体时,它似乎是违反直觉的。
当'data_class'选项设置为null时,隐藏的项目字段包含项目ID,并且在提交时,在创建的实体上调用getProject()将返回正确的项目对象。