简体   繁体   中英

Validation form with Symfony 3 and FOSrestBundle

I'm following a tutorial about making some REST api based on FOSrestBundle but I got stuck in a part about forms validation.

I try to add a new user in my database using a POST request at that endpoint: http://127.0.0.1:8000/users

But it only return an error about values that should not be blank.

My class UserController has this method:

/**
 * @Rest\View(statusCode=Response::HTTP_CREATED, serializerGroups={"user"})
 * @Rest\Post("/users")
 */
public function postUsersAction(Request $request)
{
    $user = new User();
    $form = $this->createForm(UserType::class, $user, ['validation_groups'=>['Default', 'New']]);

    $form->submit($request->request->all());

    if ($form->isValid()) {
        $encoder = $this->get('security.password_encoder');
        $encoded = $encoder->encodePassword($user, $user->getPlainPassword());
        $user->setPassword($encoded);

        $em = $this->get('doctrine.orm.entity_manager');
        $em->persist($user);
        $em->flush();
        return $user;
    } else {
        return $form;
    }
}

My validation.yml:

AppBundle\Entity\User:
    constraints:
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: email
    properties:
        firstname:
            - NotBlank: ~
            - Type: string
        lastname:
            - NotBlank: ~
            - Type: string
        email:
            - NotBlank: ~
            - Email: ~
        plainPassword:
            - NotBlank: { groups: [New, FullUpdate] }
            - Type: string
            - Length:
                min: 4
                max: 50

Here is my entity User:

/**
* @ORM\Entity()
* @ORM\Table(name="users",
*      uniqueConstraints={@ORM\UniqueConstraint(name="users_email_unique",columns={"email"})}
* )
*/
class User implements UserInterface
{
   /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $firstname;

    /**
     * @ORM\Column(type="string")
     */
    protected $lastname;

    /**
     * @ORM\Column(type="string")
     */
    protected $email;

    /**
     * @ORM\Column(type="string")
     */
    protected $password;

    protected $plainPassword;

    public function getId()
    {
        return $this->id;
    }

    public function setId($id)
    {
        $this->id = $id;
    }

    public function getFirstname()
    {
        return $this->firstname;
    }

    public function setFirstname($firstname)
    {
        $this->firstname = $firstname;
    }

    public function getLastname()
    {
        return $this->lastname;
    }

    public function setLastname($lastname)
    {
        $this->lastname = $lastname;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function setPassword($password)
    {
        $this->password = $password;
    }

    public function getPlainpassword()
    {
        return $this->plainPassword;
    }

    public function getRoles()
    {
        return [];
    }

    public function getSalt()
    {
        return null;
    }

    public function getUsername()
    {
        return $this->email;
    }

    public function eraseCredentials()
    {
        // Suppression des données sensibles
        $this->plainPassword = null;
    }
}

And the part who create the form in UserType.php:

namespace AppBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\EmailType;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('firstname');
        $builder->add('lastname');
        $builder->add('plainPassword');
        $builder->add('email', EmailType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\User',
            'csrf_protection' => false,
            "allow_extra_fields" => true
        ]);
    }
}

I use Postman to send my POST request, with that payload:

{
    "firstname": "foo",
    "lastname": "bar",
    "email": "test@test.com",
    "password": "qwerty"
}

But I receive an 400 error:

{
    "code": 400,
    "message": "Validation Failed",
    "errors": {
        "children": {
            "firstname": [],
            "lastname": [],
            "plainPassword": {
                "errors": [
                    "This value should not be blank."
                ]
            },
            "email": []
        }
    }
}

EDIT 1

If I replace plainPassword by password in my validation.yml, that error will be return:

{
    "code": 400,
    "message": "Validation Failed",
    "errors": {
        "errors": [
            "This value should not be blank."
        ],
        "children": {
            "firstname": [],
            "lastname": [],
            "plainPassword": [],
            "email": []
        }
    }
}

If you need to view other files tell me.

Anyway, thanks for your help!

RESOLVED

So @kunicmarko20 thankfully helped me, I made an error in the payload that I send with POST request, here's the correct one:

{
    "firstname": "foo",
    "lastname": "bar",
    "email": "test@test.com",
    "plainPassword": "qwerty"
}

And more than anything, I completely forget to put a setter in my User entity, here we go:

public function getPlainPassword()
{
    return $this->plainPassword;
}

public function setPlainPassword($plainpassword)
{
    $this->plainPassword = $plainpassword;
}

If you are going to use $form->submit() then the value you pass to it should be an array, and it would look like:

$data = json_decode($request->getContent(), true);
$form->submit($data);

Have exactly the same thing and it works without a problem.

Edit:

I just took another look and you are defining plainPassword and sending password in your json, try like this:

{
    "firstname": "foo",
    "lastname": "bar",
    "email": "test@test.com",
    "plainPassword": "qwerty"
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM