Symfony REST api-实体关联字段->;值无效

Symfony REST api-实体关联字段->;值无效,api,symfony,fosrestbundle,jmsserializerbundle,validationerror,Api,Symfony,Fosrestbundle,Jmsserializerbundle,Validationerror,在Symfony中,我正在为Angular2编写一个API。我将FOSRestBundle与JMSSerializerBundle一起使用。现在,我有一个实体“User”,它有一个实体字段“address”,带有一个OneToOne关联。我在保存用户地址时遇到问题 因此,我首先获取用户对象,它返回整个对象,地址为json。然后我把请求和那个完全相同的对象放在一起。在我的PUT函数中,我使用Symfony表单验证数据,然后返回一个错误: { "children": { "address

在Symfony中,我正在为Angular2编写一个API。我将FOSRestBundle与JMSSerializerBundle一起使用。现在,我有一个实体“User”,它有一个实体字段“address”,带有一个OneToOne关联。我在保存用户地址时遇到问题

因此,我首先获取用户对象,它返回整个对象,地址为json。然后我把请求和那个完全相同的对象放在一起。在我的PUT函数中,我使用Symfony表单验证数据,然后返回一个错误:

{
  "children": {
    "address": {
      "errors": [
        "This value is not valid."
      ]
    }
  }
}
我的用户实体上还有一些其他字段,当我在表单生成器中省略address字段时,这些字段会保存得很好。顺便说一句:我省略了其他字段,以避免代码量过载

我使用以下版本:

  • symfony:3.1
  • jms/序列化程序:1.1
  • friendsofsymfony/rest捆绑包:2.0
我已经找了两天了,但我找不到任何能帮助我解决这个问题的东西。我使用日期转换,如FOSRestBundle所述:

我希望我的问题表达得足够好,提供了足够的信息

以下是我的简化代码:

用户类别:

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * @ORM\Entity
 */
class User
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToOne(targetEntity="Address", cascade={"persist", "remove"}, orphanRemoval=true)
     * @JMS\Type("AppBundle\Entity\Address")
     */
    private $address;
地址类别:

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Address
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string")
     */
    private $street;

    /**
     * @ORM\Column(type="string")
     */
    private $number;

    /**
     * @ORM\Column(type="string")
     */
    private $postalCode;

    /**
     * @ORM\Column(type="string")
     */
    private $city;

    /**
     * @ORM\Column(type="string")
     */
    private $country;
用户类型类:

use FOS\RestBundle\Form\Transformer\EntityToIdObjectTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class UserType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // Data transformation needed for relationship entities
        $addressTransformer = new EntityToIdObjectTransformer($options['em'], 'AppBundle:Address');

        $builder
            ->add($builder->create('address', TextType::class)->addModelTransformer($addressTransformer))
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User',
            'csrf_protection'   => false,
            'allow_extra_fields' => true,
            'em' => null
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'user';
    }
}
UserController类:

use AppBundle\Entity\User;
use AppBundle\Form\UserType;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\View\View;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;

/**
 * Class UserController
 * @package AppBundle\Controller
 */
class UserController extends Controller
{
    /**
     * @Rest\View
     * @Route("/users/{id}")
     * @Method("PUT")
     */
    public function putAction(Request $request, $id)
    {
        $user = $this->getEntity($id);
        $form = $this->createForm(UserType::class, $user, array(
            'method' => 'PUT',
            'em' => $this->getDoctrine()->getManager()
        ));

        $form->handleRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();

            $em->persist($user);
            $em->flush();

            $response = new Response();
            $response->setStatusCode(204);
            $response->setContent('User saved!');

            return $response;
        }

        return View::create($form, 400);
    }


    /**
     * @Rest\View
     * @Route("/users/{id}", requirements={"id": "\d+"})
     * @Method("GET")
     */
    public function getAction($id)
    {
        $user = $this->getEntity($id);

        return array('user' => $user);
    }

    /**
     * Get the User entity object by the given ID and return it
     *
     * @param $id
     *
     * @return User
     */
    private function getEntity($id)
    {
        $user = $this->getDoctrine()->getRepository('AppBundle:User')->find($id);

        if (!$user instanceof User) {
            throw new NotFoundHttpException('User not found');
        }

        return $user;
    }
我获取并放置的json对象如下所示:

{
"user":
    {
        "id":1,
        "address": {
            "id":1,
            "street":"Teststreet",
            "number":"1",
            "postalCode":"9999",
            "city":"Citytest",
            "country":"Countrytest"
        }
    }
}
my config.yml:

fos_rest:
    param_fetcher_listener: true
    body_listener:
        array_normalizer: fos_rest.normalizer.camel_keys
    format_listener:
        rules:
            path: ^/
            fallback_format: json
            prefer_extension: false
            priorities: [json, xml]
    body_converter:
        enabled:              false
        validate:             false
    view:
        view_response_listener: force
        formats:
            json: true
            xml: true
        templating_formats:
            html: true
        force_redirects:
            html: true
        failed_validation: HTTP_BAD_REQUEST
        default_engine: twig
        mime_types:
            json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1']
    routing_loader:
        default_format: json
    serializer:
        serialize_null: true

nelmio_api_doc: ~

jms_serializer:
    metadata:
        directories:
            FOSUB:
                namespace_prefix: "FOS\\UserBundle"
                path: "%kernel.root_dir%/serializer/FOSUserBundle"

我做过类似的事情,我没有在表单类型中使用任何模型转换器。这是我的密码

用户类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('address', AddressType::class)
    ;
}
地址类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('street', AddressType::class)
        ->add('number', AddressType::class)
        ->add('postalCode', AddressType::class)
        // ...
    ;
}
以及要放置的json对象

{
"user":
    {
        "address": {
            "street":"Teststreet",
            "number":"1",
            "postalCode":"9999",
            "city":"Citytest",
            "country":"Countrytest"
        }
    }
}

我做过类似的事情,我没有在表单类型中使用任何模型转换器。这是我的密码

用户类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('address', AddressType::class)
    ;
}
地址类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('street', AddressType::class)
        ->add('number', AddressType::class)
        ->add('postalCode', AddressType::class)
        // ...
    ;
}
以及要放置的json对象

{
"user":
    {
        "address": {
            "street":"Teststreet",
            "number":"1",
            "postalCode":"9999",
            "city":"Citytest",
            "country":"Countrytest"
        }
    }
}