Проблема исправлена, проверьте мой ответ.
Я создаю конечную точку регистрации на моем Symfony2.7 rest api. Я использую FosRestBundle и FosUserBundle
Вот модель пользователя:
<?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 } }
\ Вот форма UserType: \
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'; } }
И это пост-пользовательский контроллер:
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, ); }
Проблема заключается в том, что когда я отправляю неверную информацию или пустую информацию, сервер возвращает ошибку с плохими формами 500 с данными доктрины / mysql нулевого значения для не нулевой строки в состоянии ответа json со списком плохих образованных записей.
Любая идея о том, как исправить это поведение? Как получилось, что проверка прошла
Хорошо, потратив много времени на чтение кода FOSUserBundle, и особенно контроллера регистрации и фабрики форм, я придумал полностью работающее решение.
Прежде чем что-либо делать, не забудьте отключить CSRF в конфигурации symfony2.
Вот контроллер, который я использую для регистрации:
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); }
Теперь сложная часть представляла форму с помощью REST. Проблема заключалась в том, что когда я отправил i JSON, как этот:
{ "email":"xxxxx@xxxx.com", "username":"xxx", "plainPassword":{ "first":"xxx", "second":"xxx" } }
API ответил, как ничто не было отправлено.
Решение состоит в том, что Symfony2 ждет вас, чтобы инкапсулировать данные формы в имя формы!
Вопрос был: «Я не создал эту форму, поэтому я не знаю, как ее зовут». Поэтому я снова пошел в код пакета и выяснил, что тип формы был fos_user_registration, а функция getName возвращала fos_user_registration_form.
В результате я попытался представить свой JSON таким образом:
{"fos_user_registration_form":{ "email":"xxxxxx@xxxxxxx.com", "username":"xxxxxx", "plainPassword":{ "first":"xxxxx", "second":"xxxxx" } }}
И вуаля! это сработало. Если вы пытаетесь настроить свой fosuserbundle с помощью fosrestbundle и LexikJWTAuthenticationBundle, просто спросите меня, я буду рад помочь.
Другой способ – это регистрация без форм из FOSUserBundle. Сделайте запрос POST с параметрами: электронной почтой, пользователем, паролем.
public function postUserAction(Request $request) { $userManager = $this->get('fos_user.user_manager'); $email = $request->request->get('email'); $username = $request->request->get('user'); $password = $request->request->get('password'); $email_exist = $userManager->findUserByEmail($email); $username_exist = $userManager->findUserByUsername($username); if($email_exist || $username_exist){ $response = new JsonResponse(); $response->setData("Username/Email ".$username."/".$email." existiert bereits"); return $response; } $user = $userManager->createUser(); $user->setUsername($username); $user->setEmail($email); $user->setLocked(false); $user->setEnabled(true); $user->setPlainPassword($password); $userManager->updateUser($user, true); $response = new JsonResponse(); $response->setData("User: ".$user->getUsername()." wurde erstellt"); return $response; }
@Adel 'Sean' Helal ваш способ не работает, по крайней мере, с последними версиями FOSRestBundle, FOSUserBundle и Symfony с Flex. Я почти стрелял в голову, пытаясь заставить его работать. В конце я нашел решение, и это довольно просто. Требуется только разбор запроса.
Фрагмент моего кода контроллера
... $form->setData($user); // THIS LINE DO THE MAGIC $data = json_decode($request->getContent(), true); if ($data === null) { throw new BadRequestHttpException(); } $form->submit($data); if ( ! $form->isValid()) { $event = new FormEvent($form, $request); $dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event); if (null !== $response = $event->getResponse()) { return $response; } return new JsonResponse($this->getFormErrors($form), Response::HTTP_BAD_REQUEST); } ...
Зависимости composer.json :
... "symfony/lts": "^3", "symfony/flex": "^1.0", "friendsofsymfony/rest-bundle": "^2.3", "friendsofsymfony/user-bundle": "^2.0", "lexik/jwt-authentication-bundle": "^2.4", ...
Мой функциональный тестовый код:
namespace App\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\DependencyInjection\Container; class ApiUserControllerTest extends WebTestCase { /** * @var Container */ private $container; public function setUp() { self::bootKernel(); $this->container = self::$kernel->getContainer(); } public function testRegistration() { $userData = [ 'username' => 'test', 'email' => 'test@email.com', 'plainPassword' => [ 'first' => 'test123', 'second' => 'test123' ] ]; $client = $this->container->get('eight_points_guzzle.client.rest'); $response = $client->post( 'api/registration', ['json' => $userData] ); $bodyResponse = \GuzzleHttp\json_decode($response->getBody(), true); $this->assertEquals(201, $response->getStatusCode()); $this->assertArrayHasKey('token', $bodyResponse); $this->assertNotEmpty($bodyResponse['token']); } }