Problem fixed, check my answer.
I'm building a registration endpoint on my Symfony2.7 rest api. I am using FosRestBundle and FosUserBundle
Here is the user model :
<?php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
*/
class User extends BaseUser {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct() {
parent::__construct();
// your own logic
}
}
\ Here is the UserType form : \
class UserType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', 'email')
->add('username', null)
->add('plainPassword', 'repeated', array(
'type' => 'password',
'first_options' => array('label' => 'password'),
'second_options' => array('label' => 'password_confirmation'),
))
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\User',
'csrf_protection' => false,
));
}
/**
* @return string
*/
public function getName()
{
return 'user';
}
}
And this the post user controller :
public function postUserAction(\Symfony\Component\HttpFoundation\Request $request) {
$user = new \AppBundle\Entity\User();
$form = $this->createForm(new \AppBundle\Form\UserType(), $user);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
$view = $this->view(array('token'=>$this->get("lexik_jwt_authentication.jwt_manager")->create($user)), Codes::HTTP_CREATED);
return $this->handleView($view);
}
return array(
'form' => $form,
);
}
The problem is that when i submit wrong information, or empty information, the server return a bad formated 500 error with doctrine / mysql details of null value for not null row in state of a json response with the list of bad formated entries.
Any idea on how to fix this behaviour ? How come the validation get by passed and
Ok after spending a lot of time reading the FOSUserBundle code, and particularly the registration controller and the form factory, i came up with a fully working solution.
Before doing anything don't forget to disable CSRF in your symfony2 configuration.
Here is the controller I use to register :
public function postUserAction(\Symfony\Component\HttpFoundation\Request $request) {
/** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->get('fos_user.registration.form.factory');
/** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->createUser();
$user->setEnabled(true);
$event = new \FOS\UserBundle\Event\GetResponseUserEvent($user, $request);
$dispatcher->dispatch(\FOS\UserBundle\FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
$event = new \FOS\UserBundle\Event\FormEvent($form, $request);
$dispatcher->dispatch(\FOS\UserBundle\FOSUserEvents::REGISTRATION_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new \Symfony\Component\HttpFoundation\RedirectResponse($url);
}
$dispatcher->dispatch(\FOS\UserBundle\FOSUserEvents::REGISTRATION_COMPLETED, new \FOS\UserBundle\Event\FilterUserResponseEvent($user, $request, $response));
$view = $this->view(array('token' => $this->get("lexik_jwt_authentication.jwt_manager")->create($user)), Codes::HTTP_CREATED);
return $this->handleView($view);
}
$view = $this->view($form, Codes::HTTP_BAD_REQUEST);
return $this->handleView($view);
}
Now the tricky part was submiting the form using REST. The problem was that when I sent i JSON like this one :
{
"email":"[email protected]",
"username":"xxx",
"plainPassword":{
"first":"xxx",
"second":"xxx"
}
}
The API was responding like nothing was submited.
The solution is that Symfony2 is waiting for you to encapsulate your form data in the form name !
The question was "I didnt create this form so i dont know what is its name..". So i went again in the bundle code and found out that the form type was fos_user_registration and the getName function was returning fos_user_registration_form.
As a result i tried to submit my JSON this way :
{"fos_user_registration_form":{
"email":"[email protected]",
"username":"xxxxxx",
"plainPassword":{
"first":"xxxxx",
"second":"xxxxx"
}
}}
And voila! it worked. If you are struggling setting up your fosuserbundle with fosrestbundle and LexikJWTAuthenticationBundle just ask me i'll be glad to help.