我正在使用Symfony 2.7.39和FOSRestBundle来构建一个简单的REST api . 在这种情况下,我有这个实体:

class DocumentacionMaquina extends Documentacion
    {
      /**
       * @ORM\ManyToOne(targetEntity="PDCA\RestBundle\Entity\Archivo", cascade={"all"})
       * @ORM\JoinColumn(name="declaracion_conformidad_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
       *
       * @Serializer\Groups({"details"})
       */
      private $declaracion_conformidad;
        // ...
    }

ArchivoType:

class ArchivoType extends AbstractType
    {
      /**
       * @param FormBuilderInterface $builder
       * @param array $options
       */
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
        $builder->add('nombre');
      }

      public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
          'data_class' => 'PDCA\RestBundle\Entity\Archivo',
          'csrf_protection' => false,
          'cascade_validation' => true
        ));
      }
    }

DocumentacionMaquinaType:

class DocumentacionMaquinaType extends DocumentacionType
    {
      /**
       * @param FormBuilderInterface $builder
       * @param array $options
       */
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
        parent::buildForm($builder, $options); 

     $builder
      ->add('maquina', 'entity', array(
        'class' => 'PDCA\RestBundle\Entity\Maquina' 
      ))
      ->add('declaracion_conformidad', new ArchivoType(),
        array('required'=>false)
      )
    ;
  }

  public function configureOptions(OptionsResolver $resolver) {
    $resolver->setDefaults(array(
      'data_class' => 'PDCA\RestBundle\Entity\DocumentacionMaquina',
      'csrf_protection' => false,
      'cascade_validation' => true
    ));
    }
}

当我创建一个新的DocumentacionMaquina实体启动POST时,它按预期工作:

{
    "pdca_restbundle_documentacion":
      {
        "maquina": 752,
        "declaracion_conformidad": {
        "nombre": "fichero10"
      }
    }

但我想发送一个null(编辑实体并使用可选的Archivo创建新实体):

{
    "pdca_restbundle_documentacion":
      {
        "maquina": 752,
        "declaracion_conformidad": null
    }

这是我发送空值时的验证错误:

此值无效 .

在我的控制器中:

$entity = new DocumentacionMaquina();
    $form = $this->createForm(new DocumentacionMaquinaType(), $entity, array('method' => $request->getMethod()));

    $form->submit($request->get($form->getName()), false);

    if !($form->isValid()) {
        return $this->view(array('form' => $form), Codes::HTTP_BAD_REQUEST);
    }

任何帮助将不胜感激 .


EDIT #1 我创建了一个简单的实体,没有继承用于测试,但结果相同 .

实体Prueba:

namespace PDCA\RestBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
/**
 * @ORM\Entity
 */
class Prueba
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     *
     * @Serializer\Groups({"list", "details"})
     */
    private $id;
    /**
     * @ORM\ManyToOne(targetEntity="PDCA\RestBundle\Entity\Hijo", cascade={"all"})
     * @ORM\JoinColumn(name="marcado_ce_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
     *
     * @Serializer\Groups({"list", "details"})
     */
    private $marcado_ce;
    /**
     * @ORM\Column(type="string", unique=false, length=255, nullable=false)
     *
     * @Serializer\Groups({"list", "details"})
     *
     * @Assert\NotBlank()
     * @Assert\Length(max=255)
     */
    private $nombre;
    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set marcado_ce
     *
     * @param \DateTime $marcado_ce
     * @return Prueba
     */
    public function setMarcadoCe(Hijo $marcado_ce = null)
    {
        $this->marcado_ce = $marcado_ce;

        return $this;
    }
    /**
     * Get marcado_ce
     *
     * @return \DateTime
     */
    public function getMarcadoCe()
    {
        return $this->marcado_ce;
    }
    /**
     * Set nombre
     *
     * @param string $nombre
     * @return Prueba
     */
    public function setNombre($nombre)
    {
        $this->nombre = $nombre;

        return $this;
    }
    /**
     * Get nombre
     *
     * @return string
     */
    public function getNombre()
    {
        return $this->nombre;
    }
}

实体Hijo

namespace PDCA\RestBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
/**
 * @ORM\Entity
 *
 */
class Hijo
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     *
     * @Serializer\Groups({"list", "details", "backend_creacion"})
     */
    private $id;
        /**
     * @ORM\Column(type="string", unique=false, length=255, nullable=false)
     *
     * @Serializer\Groups({"list", "details"})
     *
     * @Assert\NotBlank()
     * @Assert\Length(max=255)
     */
    private $nombre;
    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set nombre
     *
     * @param string $nombre
     * @return Artchivo
     */
    public function setNombre($nombre)
    {
        $this->nombre = $nombre;

        return $this;
    }
    /**
     * Get nombre
     *
     * @return string
     */
    public function getNombre()
    {
        return $this->nombre;
    }
}

PruebaType和HijoType:

namespace PDCA\RestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use PDCA\RestBundle\Entity\Prueba;
class PruebaType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('nombre')
        ->add('marcado_ce', new HijoType(), array('required'=>false))
        ;
    }
    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        /** @var OptionResolver $resolver */
        $this->configureOptions($resolver);
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
                'data_class' => 'PDCA\RestBundle\Entity\Prueba',
                'csrf_protection' => false
        ));
    }
    /**
     * @return string
     */
    public function getName()
    {
        return 'pdca_restbundle_prueba';
    }
}

输入Hijo

namespace PDCA\RestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class HijoType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('nombre')
        ;
    }
    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        /** @var OptionResolver $resolver */
        $this->configureOptions($resolver);
    }
    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
                'data_class' => 'PDCA\RestBundle\Entity\Hijo',
                'csrf_protection' => false
        ));
    }
    /**
     * @return string
     */
    public function getName()
    {
        return null;
    }
}

控制器:

$entity = new Prueba();
$form = $this->createForm(new PruebaType(), $entity, array('method' => $request->getMethod()));

$form->submit($request->get($form->getName()), false);

if ($form->isValid()) {
    //Persist $entity
}
return $this->view(array('form' => $form), Codes::HTTP_BAD_REQUEST);

当我使用子实体进行POST时,实体Prueba和Hija会持续存在:

{
    "pdca_restbundle_prueba": {
         "nombre": "nombre prueba",
          "marcado_ce": 
              {
                "nombre": "fichero4"
              }
     }
}

但是当我使用“marcado_ce”时:null:

{
    "pdca_restbundle_prueba": {
         "nombre": "nombre prueba2",
          "marcado_ce": null
     }
}

此消息失败:

{
    "code": 400,
    "message": "Validation Failed",
    "errors": {
        "errors": [
            "Este valor no es valido."
        ],
        "children": {
            "nombre": {},
            "marcado_ce": {
                "children": {
                    "nombre": {}
                }
            }
        }
    }
}

调试此问题,这里是代码启动异常导致验证失败的地方:File Form.php,第570行:

if ($this->config->getCompound()) {
      if (null === $submittedData) {
          $submittedData = array();
      }

      if (!is_array($submittedData)) {
          **throw new TransformationFailedException('Compound forms expect an array or NULL on submission.');**
      }

我在这里上传了一个带有堆栈跟踪的图像:https://i.stack.imgur.com/QzPDc.png

我用这个编辑了Form.php代码替换异常代码(第750行) . 但这不是解决方案 . 我将尝试理解根本原因是什么,也许我会想念symfony-forms .

if (!is_array($submittedData)) {
  $submittedData = array();
}