设置注册 FOSUserBundle 和 FOSRestBundle REST API
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';
}
}
这是 post 用户控制器:
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,
);
}
问题是,当我提交错误信息或空信息时,服务器 return 格式错误的 500 错误与原则 / mysql 状态下非空行的空值详细信息json 响应,其中包含格式错误的条目列表。
知道如何解决这个问题吗?
怎么验证通过了
好的,在花了很多时间阅读 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 提交表单。问题是,当我像这样发送 JSON 时:
{
"email":"xxxxx@xxxx.com",
"username":"xxx",
"plainPassword":{
"first":"xxx",
"second":"xxx"
}
}
API 的响应就像没有提交任何内容一样。
解决办法是Symfony2等着你把你的表单数据封装在表单名中!
问题是 "I didnt create this form so i dont know what is its name.."。
所以我再次进入捆绑代码,发现表单类型是 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']);
}
}
问题已解决,请查看我的回答。
我正在我的 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';
}
}
这是 post 用户控制器:
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,
);
}
问题是,当我提交错误信息或空信息时,服务器 return 格式错误的 500 错误与原则 / mysql 状态下非空行的空值详细信息json 响应,其中包含格式错误的条目列表。
知道如何解决这个问题吗? 怎么验证通过了
好的,在花了很多时间阅读 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 提交表单。问题是,当我像这样发送 JSON 时:
{
"email":"xxxxx@xxxx.com",
"username":"xxx",
"plainPassword":{
"first":"xxx",
"second":"xxx"
}
}
API 的响应就像没有提交任何内容一样。
解决办法是Symfony2等着你把你的表单数据封装在表单名中!
问题是 "I didnt create this form so i dont know what is its name.."。 所以我再次进入捆绑代码,发现表单类型是 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']);
}
}