具有自定义 FormType 的 Symfony2 Form 在两个方向上调用具有相同数据的 DataTransformer
Symfony2 Form with custom FormType calls DataTransformer with same data in both directions
我创建了一个新的 FormType,它通过
扩展了 entity
类型
//...
public function getParent()
{
return 'entity';
}
这导致我的编辑表单抱怨整数不是 My/Entity/Type
,我需要一个数据转换器。所以我创造了一个。这是精简版(只是基础教程版)
//...
public function reverseTransform($val)
{
// Entity to int
return $val->getId();
}
public function transform($val)
{
// Int to Entity
return $repo->findOneBy($val);
}
//...
然后将其添加到我的表单类型中
//...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addViewTransformer(new IdToMyModelTransformer($this->em));
}
这修复了我查看我的表单的问题,但现在当我使用从我的自定义小部件中选择的实体提交表单时,它会尝试调用 transform
而不是 reverseTransform
并使用 $val
作为->getId()
的 int 在非对象上失败。
我想不出正确的方法。如果我使用 'choice'
作为我的小部件父级,我会遇到一组不同的问题(触发选择默认约束说它是无效数据?)
我需要一个实体传递给我的小部件,以便它可以提取元数据进行显示,但我当然不能 post 一个实体返回。我该如何告诉表格?
尝试设置 'data_class' => null
但没有成功。检查网络选项卡显示 post 填写表单时值已正确发送。
更新 1
所以我重新阅读了 DataTransformer 页面,那个图表让我开始思考,尤其是在上面的橡皮鸭编程之后,我询问实体的表单,但希望它接收整数..所以我实际上需要一个单向转换器,ViewTransformer -> 获取显示实体,从小部件中获取 posted 一个 int,不转换它 直接通过。哪个有效,我只是在更新时收到 "invalid data" 错误。
现在我的变形金刚中有:
public function transform($val)
{
// Int to Entity
return $repo->findOneBy($val);
}
public function reverseTransform($val)
{
// Do nothing
return $val;
}
更新 2
现在似乎已经修复了它,尽管出于某种原因,如果我在我的表单中 post int 2
字符串“2/”被发送到我的转换器。对此有什么想法吗?现在我正在清理变压器中的字符串,但似乎它不应该发生。
根据我在你的转换器中看到的情况 class 你没有正确实现代码。这应该是正确的实现:
namespace App\YourBundle\Form\DataTransformer;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
class IdToMyModelTransformer implements DataTransformerInterface
{
/**
* @var EntityManager
*/
private $em;
/**
* @param EntityManager $em
*/
public function __construct(EntityManager $em) {
$this->em = $em;
}
/**
* Transforms a value from the original representation to a transformed representation.
*
* This method is called on two occasions inside a form field:
*
* 1. When the form field is initialized with the data attached from the datasource (object or array).
* 2. When data from a request is submitted using {@link Form::submit()} to transform the new input data
* back into the renderable format. For example if you have a date field and submit '2009-10-10'
* you might accept this value because its easily parsed, but the transformer still writes back
* "2009/10/10" onto the form field (for further displaying or other purposes).
*
* This method must be able to deal with empty values. Usually this will
* be NULL, but depending on your implementation other empty values are
* possible as well (such as empty strings). The reasoning behind this is
* that value transformers must be chainable. If the transform() method
* of the first value transformer outputs NULL, the second value transformer
* must be able to process that value.
*
* By convention, transform() should return an empty string if NULL is
* passed.
*
* @param mixed $object The value in the original representation
*
* @return mixed The value in the transformed representation
*
* @throws TransformationFailedException When the transformation fails.
*/
public function transform($object) {
if (null === $object) {
return null;
}
return $object->getId();
}
/**
* Transforms a value from the transformed representation to its original
* representation.
*
* This method is called when {@link Form::submit()} is called to transform the requests tainted data
* into an acceptable format for your data processing/model layer.
*
* This method must be able to deal with empty values. Usually this will
* be an empty string, but depending on your implementation other empty
* values are possible as well (such as empty strings). The reasoning behind
* this is that value transformers must be chainable. If the
* reverseTransform() method of the first value transformer outputs an
* empty string, the second value transformer must be able to process that
* value.
*
* By convention, reverseTransform() should return NULL if an empty string
* is passed.
*
* @param mixed $categoryId The value in the transformed representation
*
* @return mixed The value in the original representation
*
* @throws TransformationFailedException When the transformation fails.
*/
public function reverseTransform($id) {
if (!$id || $id <= 0) {
return null;
}
if(!ctype_digit($id)){
throw new TransformationFailedException();
}
$repo = $this->em->getRepository('...');
$result = $repo->findOneBy(array('id' => $id));
if (null === $result) {
throw new TransformationFailedException(
sprintf(
'Entity with id does not exist!',
$id
)
);
}
return $result;
}
}
在 IdToMyIntType
中你会得到这样的东西:
namespace App\YourBundle\Form\Type;
use App\YourBundle\Form\DataTransformer\IdToMyModelTransformer ;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class IdToMyModelType extends AbstractType {
/**
* @var EntityManager
*/
private $em;
/**
* @param EntityManager $em
*/
public function __construct( EntityManager $em ) {
$this->em = $em;
}
public function buildForm( FormBuilderInterface $builder, array $options ) {
$transformer = new IdToMyModelTransformer ( $this->em );
$builder->addModelTransformer( $transformer );
}
public function setDefaultOptions( OptionsResolverInterface $resolver ) {
$resolver->setDefaults(array('invalid_message' => 'Something went wrong message.'));
}
public function getParent() {
return 'entity';
}
public function getName() {
return 'id_to_model_type';
}
}
我建议您查看 DataTransformerInterface
并阅读有关方法的文档。它将简要说明该方法的预期用途。此外,如果您在实施它时遇到问题,您可以随时查看 official documentation,其中包含一个工作示例并从那里构建。
根据我最近的更新,我意识到,因为我只使用我的表单数据来显示当前保存的实体关系(其余部分由 ajax 提供)并且与表单的格式不同收到它会导致一些混乱。
模型数据
这一切都保持原样(不需要模型数据转换器)
规范数据
无变化
查看数据(需要单向转换)
- 变换()
- 实体的 ID,以便小部件可以访问其他属性
- 反向变换()
- 发布的 ID 格式正确,所以我们 return 它
代码
非常简单:
private $om;
public function __construct (ObjectManager om)
{
$this->om = $om;
}
public function transform($val)
{
// Int to Entity
return $om->getRepository('MyBundle:EntityName')->findOneBy($val);
}
public function reverseTransform($val)
{
// Do nothing
return $val;
}
希望这能帮助那些让自己的要求感到困惑的其他人!
我创建了一个新的 FormType,它通过
扩展了entity
类型
//...
public function getParent()
{
return 'entity';
}
这导致我的编辑表单抱怨整数不是 My/Entity/Type
,我需要一个数据转换器。所以我创造了一个。这是精简版(只是基础教程版)
//...
public function reverseTransform($val)
{
// Entity to int
return $val->getId();
}
public function transform($val)
{
// Int to Entity
return $repo->findOneBy($val);
}
//...
然后将其添加到我的表单类型中
//...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addViewTransformer(new IdToMyModelTransformer($this->em));
}
这修复了我查看我的表单的问题,但现在当我使用从我的自定义小部件中选择的实体提交表单时,它会尝试调用 transform
而不是 reverseTransform
并使用 $val
作为->getId()
的 int 在非对象上失败。
我想不出正确的方法。如果我使用 'choice'
作为我的小部件父级,我会遇到一组不同的问题(触发选择默认约束说它是无效数据?)
我需要一个实体传递给我的小部件,以便它可以提取元数据进行显示,但我当然不能 post 一个实体返回。我该如何告诉表格?
尝试设置 'data_class' => null
但没有成功。检查网络选项卡显示 post 填写表单时值已正确发送。
更新 1
所以我重新阅读了 DataTransformer 页面,那个图表让我开始思考,尤其是在上面的橡皮鸭编程之后,我询问实体的表单,但希望它接收整数..所以我实际上需要一个单向转换器,ViewTransformer -> 获取显示实体,从小部件中获取 posted 一个 int,不转换它 直接通过。哪个有效,我只是在更新时收到 "invalid data" 错误。
现在我的变形金刚中有:
public function transform($val)
{
// Int to Entity
return $repo->findOneBy($val);
}
public function reverseTransform($val)
{
// Do nothing
return $val;
}
更新 2
现在似乎已经修复了它,尽管出于某种原因,如果我在我的表单中 post int 2
字符串“2/”被发送到我的转换器。对此有什么想法吗?现在我正在清理变压器中的字符串,但似乎它不应该发生。
根据我在你的转换器中看到的情况 class 你没有正确实现代码。这应该是正确的实现:
namespace App\YourBundle\Form\DataTransformer;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
class IdToMyModelTransformer implements DataTransformerInterface
{
/**
* @var EntityManager
*/
private $em;
/**
* @param EntityManager $em
*/
public function __construct(EntityManager $em) {
$this->em = $em;
}
/**
* Transforms a value from the original representation to a transformed representation.
*
* This method is called on two occasions inside a form field:
*
* 1. When the form field is initialized with the data attached from the datasource (object or array).
* 2. When data from a request is submitted using {@link Form::submit()} to transform the new input data
* back into the renderable format. For example if you have a date field and submit '2009-10-10'
* you might accept this value because its easily parsed, but the transformer still writes back
* "2009/10/10" onto the form field (for further displaying or other purposes).
*
* This method must be able to deal with empty values. Usually this will
* be NULL, but depending on your implementation other empty values are
* possible as well (such as empty strings). The reasoning behind this is
* that value transformers must be chainable. If the transform() method
* of the first value transformer outputs NULL, the second value transformer
* must be able to process that value.
*
* By convention, transform() should return an empty string if NULL is
* passed.
*
* @param mixed $object The value in the original representation
*
* @return mixed The value in the transformed representation
*
* @throws TransformationFailedException When the transformation fails.
*/
public function transform($object) {
if (null === $object) {
return null;
}
return $object->getId();
}
/**
* Transforms a value from the transformed representation to its original
* representation.
*
* This method is called when {@link Form::submit()} is called to transform the requests tainted data
* into an acceptable format for your data processing/model layer.
*
* This method must be able to deal with empty values. Usually this will
* be an empty string, but depending on your implementation other empty
* values are possible as well (such as empty strings). The reasoning behind
* this is that value transformers must be chainable. If the
* reverseTransform() method of the first value transformer outputs an
* empty string, the second value transformer must be able to process that
* value.
*
* By convention, reverseTransform() should return NULL if an empty string
* is passed.
*
* @param mixed $categoryId The value in the transformed representation
*
* @return mixed The value in the original representation
*
* @throws TransformationFailedException When the transformation fails.
*/
public function reverseTransform($id) {
if (!$id || $id <= 0) {
return null;
}
if(!ctype_digit($id)){
throw new TransformationFailedException();
}
$repo = $this->em->getRepository('...');
$result = $repo->findOneBy(array('id' => $id));
if (null === $result) {
throw new TransformationFailedException(
sprintf(
'Entity with id does not exist!',
$id
)
);
}
return $result;
}
}
在 IdToMyIntType
中你会得到这样的东西:
namespace App\YourBundle\Form\Type;
use App\YourBundle\Form\DataTransformer\IdToMyModelTransformer ;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class IdToMyModelType extends AbstractType {
/**
* @var EntityManager
*/
private $em;
/**
* @param EntityManager $em
*/
public function __construct( EntityManager $em ) {
$this->em = $em;
}
public function buildForm( FormBuilderInterface $builder, array $options ) {
$transformer = new IdToMyModelTransformer ( $this->em );
$builder->addModelTransformer( $transformer );
}
public function setDefaultOptions( OptionsResolverInterface $resolver ) {
$resolver->setDefaults(array('invalid_message' => 'Something went wrong message.'));
}
public function getParent() {
return 'entity';
}
public function getName() {
return 'id_to_model_type';
}
}
我建议您查看 DataTransformerInterface
并阅读有关方法的文档。它将简要说明该方法的预期用途。此外,如果您在实施它时遇到问题,您可以随时查看 official documentation,其中包含一个工作示例并从那里构建。
根据我最近的更新,我意识到,因为我只使用我的表单数据来显示当前保存的实体关系(其余部分由 ajax 提供)并且与表单的格式不同收到它会导致一些混乱。
模型数据
这一切都保持原样(不需要模型数据转换器)
规范数据
无变化
查看数据(需要单向转换)
- 变换()
- 实体的 ID,以便小部件可以访问其他属性
- 反向变换()
- 发布的 ID 格式正确,所以我们 return 它
代码
非常简单:
private $om;
public function __construct (ObjectManager om)
{
$this->om = $om;
}
public function transform($val)
{
// Int to Entity
return $om->getRepository('MyBundle:EntityName')->findOneBy($val);
}
public function reverseTransform($val)
{
// Do nothing
return $val;
}
希望这能帮助那些让自己的要求感到困惑的其他人!