Symfony2 REST API始终返回false验证表单

时间:2014-09-17 22:34:47

标签: rest symfony fosrestbundle

我正在跟随Web API REST with Symfony2使用Fosrestbundle和JMS Serializer在symfony2中构建REST API,并且对于GET路由完美但不是POST,因为当我验证表单时总是返回false,甚至我都遵循函数的流程和最后一步在$ form-> isValid()中返回true,所以我很困惑。

甚至没有考虑到validations.yml文件所以,是很多代码但希望你可以帮助我因为两天我一直试图找出问题

config.yml

imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: doctrine_extensions.yml }

framework:
    validation:      { enable_annotations: true }

orm:
    auto_generate_proxy_classes: "%kernel.debug%"
    auto_mapping: true

sensio_framework_extra:
    view: { annotations: false }
    router: { annotations: true }
    request: { converters: true }

fos_rest:
    param_fetcher_listener: true
    view:
        view_response_listener: 'force'
        formats:
            json: true
            xml:  true
        templating_formats:
            html: true
    format_listener:
        rules:
            - { path: ^/api, priorities: ['json', 'xml'], fallback_format: json, prefer_extension: false }
            - { path: ^/, priorities: ['html', '*/*'], fallback_format: html, prefer_extension: false }
    exception:
        codes:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
            'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
        messages:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': true
    allowed_methods_listener: true
    access_denied_listener:
        json: true
    body_listener: true
    disable_csrf_role: ROLE_API

validations.yml

# src/Acme/MyBundle/Resources/config/validation.yml
Acme\MyBundle\Entity\Vendor:
    properties:
        name:
            - NotBlank: ~
            - NotNull: ~
            - Length:
                min: 2
                max: 50
                minMessage: "Your name must be at least {{ limit }} characters length"
                maxMessage: "Your name cannot be longer than {{ limit }} characters length"
        email:
            - Email:
                message: "The email {{ value }} is not a valid email"
                checkMX: true

        password:
            - NotBlank: ~
            - NotNull: ~

供应商实体

<?php

namespace Acme\MyBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Acme\MyBundle\Model\VendorInterface;

use Gedmo\Mapping\Annotation as Gedmo;

use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Exclude;
use JMS\Serializer\Annotation\Expose;
use JMS\Serializer;

/**
 * Vendor
 *
 * @ORM\Table(name="vendors")
 * @ORM\Entity()
 * @ExclusionPolicy("all")
 */
class Vendor implements VendorInterface
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @Expose
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=50)
     * @Expose
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="email", type="string", length=50)
     * @Expose
     */
    private $email;

    /**
     * @var string
     *
     * @ORM\Column(name="password", type="string", length=255)
     */
    private $password;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="string", length=200)
     */
    private $description;

    /**
     * @var string
     *
     * @ORM\Column(name="picture", type="string", length=50)
     * @Expose
     */
    private $picture;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="created_at", type="datetime")
     * @Gedmo\Timestampable(on="create")
     * @Expose
     */
    private $createdAt;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="updated_at", type="datetime")
     * @Gedmo\Timestampable(on="create")
     * @Expose
     */
    private $updatedAt;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Vendor
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Set email
     *
     * @param string $email
     * @return Vendor
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

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

    /**
     * Set password
     *
     * @param string $password
     * @return Vendor
     */
    public function setPassword($password)
    {
        $this->password = $password;

        return $this;
    }

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

    /**
     * Set description
     *
     * @param string $description
     * @return Vendor
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

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

    /**
     * Set picture
     *
     * @param string $picture
     * @return Vendor
     */
    public function setPicture($picture)
    {
        $this->picture = $picture;

        return $this;
    }

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

    /**
     * Set createdAt
     *
     * @param \DateTime $createdAt
     * @return Vendor
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * Get createdAt
     *
     * @return \DateTime 
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set updatedAt
     *
     * @param \DateTime $updatedAt
     * @return Vendor
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime 
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }
}

VendorController.php

<?php

namespace Acme\MyBundle\Controller;

.....


class VendorController extends FOSRestController
{
    public function postVendorAction(Request $request)
    {
        try {
            $form = new VendorType();
            $newVendor = $this->container->get('acme_mybundle.vendor.handler')->post(
                $request->request->all()
            );

            $routeOptions = array(
                'id' => $newVendor->getId(),
                '_format' => $request->get('_format')
            );

            return $this->routeRedirectView('api_get_vendor', $routeOptions, Codes::HTTP_CREATED);


        } catch (InvalidFormException $exception) {
            return $exception->getForm();
        }
    }

    protected function getOr404($id)
    {
        if (!($vendor = $this->container->get('acme_mybundle.vendor.handler')->get($id))) {
            throw new NotFoundHttpException(sprintf('The resource \'%s\' was not found.',$id));
        }

        return $vendor;
    }
}

VendorType.php

namespace Acme\MyBundle\Form;

...

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

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\MyBundle\Entity\Vendor',
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return '';
    }
}

VendiorHandler.php

    <?php

namespace Acme\MyBundle\Handler;

....

class VendorHandler implements VendorHandlerInterface
{
    private $om;
    private $entityClass;
    private $repository;
    private $formFactory;

    public function __construct(ObjectManager $om, $entityClass, FormFactoryInterface $formFactory)
    {

        $this->om = $om;
        $this->entityClass = $entityClass;
        $this->repository = $this->om->getRepository($this->entityClass);
        $this->formFactory = $formFactory;
    }

    /**
     * Create a new Vendor.
     *
     * @param array $parameters
     *
     * @return VendorInterface
     */
    public function post(array $parameters)
    {
        //die(var_dump("post handler"));

        $vendor = $this->createVendor();

        return $this->processForm($vendor, $parameters, 'POST');
    }


    /**
     * Processes the form.
     *
     * @param VendorInterface $vendor
     * @param array         $parameters
     * @param String        $method
     *
     * @return VendorInterface
     *
     * @throws \Acme\MyBundle\Exception\InvalidFormException
     */
    private function processForm(VendorInterface $vendor, array $parameters, $method = "PUT")
    {
        $form = $this->formFactory->create(new VendorType(), $vendor, array('method' => $method)); 

        $form->submit($parameters, 'PATCH' !== $method);

        if (!$form->isValid()) {
            $vendor = $form->getData();
            $this->om->persist($vendor);
            $this->om->flush($vendor);

            return $vendor;
        }

        throw new InvalidFormException('Invalid submitted data', $form);
    }

    private function createVendor()
    {
        return new $this->entityClass();
    }

}

1 个答案:

答案 0 :(得分:0)

似乎有两种简单的方法可以为您的实体设置约束。

validation.yml

yml中创建Bundle文件:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
    properties:
        name:
            - NotBlank: ~

为了使其自动运行,重要的是该文件具有相同的名称并且位于该确切的路径中。然后,您启用验证并禁用注释。

# app/config/config.yml
framework:
    validation:      { enabled: true, enable_annotations: false }

注解

您不需要任何特殊文件。只需在Entity的属性中指定约束:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    /**
     * @Assert\NotBlank()
     */
    public $name;
}

请记住启用注释:

# app/config/config.yml
framework:
    validation:      { enable_annotations: true }

问题

如果您想使用 validation.yml和注释,或者您想为验证文件使用不同的名称或路径,则必须手动加载它们。

请查看详细信息:https://stackoverflow.com/a/24210501