使用FOSRestBundle REST API设置注册FOSUserBundle


Set up registration FOSUserBundle with FOSRestBundle REST API

问题已解决,请检查我的答案

我正在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错误,在json响应的状态下,非空行的doctory/mysql详细信息为空,并带有格式错误的条目列表。

你知道如何纠正这种行为吗?验证如何通过和

好的,在花了很多时间阅读FOSUserBundle代码,特别是注册控制器和表单工厂之后,我想出了一个完全可行的解决方案。

在做任何事情之前,不要忘记在symfony2配置中禁用CSRF。

这是我用来注册的控制器:

 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提交表单

{
        "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"
        }
    }}

瞧!它奏效了。如果您在使用fosrestbundle和LexikJWTAuthenticationBundle设置fosuserbundle时遇到困难,请咨询我,我很乐意提供帮助。

另一种方法是在没有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 with 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']);
    }
}