FOS UserBundle 向注册添加所需的功能

FOS UserBundle adding needed functionality to the registration

我觉得我已经用尽了 Google 和 Fos UserBundle 的文档来寻找一种方法来初始化注册新用户时所需的基本实体。我已经重写了 RegistrationController:register 方法,并试图初始化一个名为 "Humidor" 的实体并将其添加到用户。这是它目前的样子。

    <?php

namespace UserBundle\Controller;

use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
use AppBundle\Entity\Humidor;
use Symfony\Component\HttpFoundation\Request;

use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Form\Factory\FactoryInterface;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

class RegistrationController extends BaseController
{
    public function registerAction(Request $request)
    {


        /** @var $formFactory FactoryInterface */
        $formFactory = $this->get('fos_user.registration.form.factory');
        /** @var $userManager UserManagerInterface */
        $userManager = $this->get('fos_user.user_manager');
        /** @var $dispatcher EventDispatcherInterface */
        $dispatcher = $this->get('event_dispatcher');

        $user = $userManager->createUser();
        $user->setEnabled(true);

        $event = new GetResponseUserEvent($user, $request);
        $dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);

        if (null !== $event->getResponse()) {
            return $event->getResponse();
        }

        $form = $formFactory->createForm();
        $form->setData($user);

        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            if ($form->isValid()) {
                $event = new FormEvent($form, $request);
                $dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
                $humidor = new Humidor();
                $user->addHumidor($humidor);

                $userManager->updateUser($user);

                if (null === $response = $event->getResponse()) {
                    $url = $this->getParameter('fos_user.registration.confirmation.enabled')
                        ? $this->generateUrl('fos_user_registration_confirmed')
                        : $this->generateUrl('fos_user_profile_show');

                    $response = new RedirectResponse($url);
                }

                $dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

                return $response;
            }

            $event = new FormEvent($form, $request);
            $dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);

            if (null !== $response = $event->getResponse()) {
                return $response;
            }
        }

        return $this->render('FOSUserBundle:Registration:register.html.twig', array(
            'form' => $form->createView(),
        ));
    }
}

当尝试添加调用 addHumidors() 这是我的自定义用户实体扩展 BaseUser 的方法时,我注意到 php storm 建议所有默认用户方法,但 none 来自我的自定义用户所以显然是错误的。任何关于如何通过我的自定义注册操作连接到我的自定义用户 class 的建议,甚至是关于实现此功能的更好方法的意见都将是极好的。谢谢

首先要做的事情是:因为您所做的只是 new Humidor() 一个统一的用户。您也可以将这部分作为构造函数。这类似于 Doctrine 推荐使用 Collections 的方式:

class User extends BaseUser
{
     public function __construct(Humidor $humidor = null)
     {
         // Doctrine recommends this for ToMany-associations:
         $this->humidors = new ArrayCollection();
         if (null === $humidor) {
             $humidor = new Humidor();
         }
         $this->addHumidor($humidor);
     }

     // [...the rest of your code...]
}

这样您将始终可以使用此对象,即使是在未初始化的用户上也是如此。无论您需要什么,您都可以玩这个。您可以传递一个数组而不是单个 "default" 雪茄盒,或者您也可以调整 getHumidors() 以检查它是否为空,然后创建默认雪茄盒。在任何情况下,在 User 内部处理这个问题都可以让您轻松更改一个 class 中的默认行为(而不是您调用 addHumidor() 的所有控制器)。它将确保您始终有(默认?)空雪茄盒可用。

其次,关于:

I noticed php storm suggested all of the default User methods but none from my custom user so something is obviously wrong

PhpStorm 只是猜测方法的输出,因此它是什么类型的对象。在您的情况下,您使用的是 EntityManager,它在其界面中指的是 UserInterface,它也在文档块中使用。

如果您检查 FosUserBundle\Model\UserManagerInterface::createUser(),您会注意到文档块包含 @return UserInterface。这是 PhpStorm 获取您的 UserManager returns 对象类型的地方,因为您的 User-class 具有比 addHumidor 等接口更多的方法,PhpStorm 将不知道它们。如果您想告诉 PhpStorm 有一个具有更多方法的具体对象(即您的 User-class),您可以在调用 createUser 时执行以下操作:

/** @var $user AppBundle\Entity\User */
$user = $userManager->createUser();

这应该会覆盖 PhpStorms 之前对该类型的假设,然后在下面的 if 条件中找到您的方法。如果您采纳我的第一个建议,则不必那样做,因为无论如何您都不必调用 addHumidor() 方法。

至于为什么这是必要的可能有点啰嗦,基本要点是,php 是动态类型的,PhpStorm 永远无法 100% 知道一个方法在运行时实际上会 return,因为 PHP 不会强制方法总是 return 同样的事情。这就是为什么 PhpStorm 必须猜测并且通常将文档块(或带有 php 7: specified return 类型)作为最权威的来源,因为这显然是开发人员 的意图 到 return 以及预期结果。