我正在跟随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();
}
}
答案 0 :(得分:0)
似乎有两种简单的方法可以为您的实体设置约束。
在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
和注释,或者您想为验证文件使用不同的名称或路径,则必须手动加载它们。