如何从第三个控制器使用FOSUserBundle的注册过程



我必须在数据库中保留一个实体(为了简单起见,我们称之为Entity),该实体必须引用到用FOSUserBundle处理的User为了进行此引用,我有一个列entity_table.userId

创建新的Entity时,我必须:

  1. 通过FosUserBundle的注册程序创建User
  2. 获取新建用户的ID:[元代码]$userId = $get->newCreatedUserId()
  3. Entity中设置此id:$entity->setUserId($userId)
  4. Entity持久化到数据库

如何将FosUserBundle的注册过程集成到保持我的Entity的控制器中

更多详细信息

我第一次尝试简单地从FOSUserBundle的RegistrationController的方法registerAction()中复制代码:这是一种快速而肮脏的方法,无论如何都不起作用,因为我传递的User类是错误的(我传递了我用来覆盖bundle的自定义User实体)。

这种方法还有其他缺点:

  • 我无法控制注册程序(例如,发送或决定不发送确认电子邮件)
  • 我不能对传递的数据使用内置检查
  • 我不能确定在FOSUserBundles上更新我的自定义方法是否继续工作
  • 其他我现在无法想象

所以,我想以最干净的方式创建用户:我该怎么做?哪种方法应该是好的

  1. 控制器转发
  2. 无论如何,一个模拟registerAction()方法的"硬编码"自定义方法
  3. 定制登记表

我在StackOverflow和互联网上读了很多讨论,我也读了FOSUserBundle和Symfony的文档,但我不能决定采用什么好的方法,也因为我不确定我是否理解每种方法的所有优点和缺点。

如果有人能让我走上正确的道路…:)

关于我的注册流程的更多信息

我有一个由控制器GetStarteController处理的getStarted过程。我有两种方法:

  1. indexAction(),它只显示一个字段为"电子邮件"的注册表
  2. endAction(),接收表单并使用传递的电子邮件创建一个公司(它只获取电子邮件的域部分)

这里有一个工作消息代码(对于Companies和Stores,它内部被称为源代码中存在但不在下面发布的类中的一些方法,例如setBrand()或setUrl())。

// AppBundle/Controller/getStartedController.php
namespace AppBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationTemplate;
use SymfonyComponentHttpFoundationRequest;
use MyVendorUserBundleEntityUser;
use AppBundleEntityCompanies;
use AppBundleEntityStores;
class GetStartedController extends Controller
{
    /**
     * @Route("getstarted")
     * @Template()
     */
    public function indexAction()
    {
        $data = array();
        $form = $this->createFormBuilder($data, array(
                'action' => $this->generateUrl('getStartedEnd'),
            ))
            ->add('email', 'email')
            ->add('submit', 'submit')
            ->getForm();
        return array(
            'form' => $form->createView(),
        );
    }
    /**
     * @Route("getstarted/end", name="getStartedEnd")
     * @Template()
     */
    public function endAction(Request $request)
    {
        $form = $this->createFormBuilder()
            ->add('email', 'email')
            ->add('submit', 'submit')
            ->getForm();
        $form->handleRequest($request);
        if ($form->isValid()) {
            $data = $form->getData();
        } else {
            /** @todo here we have to raise some sort of exception or error */
            echo 'no data submitted (See the todo in the code)';exit;
        }
        // Pass the email to the template
        $return['email'] = $data['email'];
        // Get the domain part of the email and pass it to the template
        $domain = explode('@', $data['email']);
        $return['domain'] = $domain[1];
        // 1) Create the new user
        $user = new User();
        // Get the token generator
        $tokenGenerator = $this->container->get('fos_user.util.token_generator');
        $user->setEmail($return['email']);
        $userRandomUsername = substr($tokenGenerator->generateToken(), 0, 12);
        $user->setUsername('random-' . $userRandomUsername);
        $plainPassword = substr($tokenGenerator->generateToken(), 0, 12);
        $encoder = $this->container->get('security.password_encoder');
        $encoded = $encoder->encodePassword($user, $plainPassword);
        // Set the password for the user
        $user->setPassword($encoded);
        /** @var $userManager FOSUserBundleModelUserManagerInterface */
        $userManager = $this->get('fos_user.user_manager');
        // Perstist the user in the database
        $userManager->updateUser($user);
        $userId = $user->getId();
        // 2) Create the Company object
        $company = new Companies();
        $company->setBrand($return['domain'])
            ->setAdded(new DateTime())
            ->setOwnerId($userId);
        // 3) Create the Store object
        $store = new Stores();
        $store->setEmail($return['email'])
            ->setUrl($return['domain'])
            ->setAdded(new DateTime());
        // Get the Entity Manager
        $em = $this->getDoctrine()->getManager();
        // Persist Company and get its ID
        $em->persist($company);
        $em->flush();
        $return['companyId'] = $company->getId();
        // Set the property branchOf of the Store object
        $store->setBranchOf($return['companyId']);
        // Persist the Store object
        $em->persist($store);
        $em->flush();
        $return['storeId'] = $store->getId();
        return $return;
    }
}

这里是改写FOSUserBundle 提供的用户实体

// MyVendor/UserBundle/Entity/User.php
namespace MyVendorUserBundleEntity;
use FOSUserBundleModelUser as BaseUser;
use DoctrineORMMapping as ORM;
/**
 * @ORMEntity
 * @ORMTable(name="prefix_user")
 */
class User extends BaseUser
{
    /**
     * @ORMId
     * @ORMColumn(type="integer")
     * @ORMGeneratedValue(strategy="AUTO")
     */
    protected $id;
    public function __construct()
    {
        parent::__construct();
        // your own logic
    }
}

Companies.php 的一些基本代码

// AppBundle/Entity/Companies.php
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
/**
 * Companies
 *
 * @ORMTable(name="companies")
 * @ORMEntity
 */
class Companies
{
    /**
     * @var integer
     *
     * @ORMColumn(name="ownerId", type="integer", nullable=false)
     */
    private $ownerid;
    /**
     * Set ownerid
     *
     * @param integer $ownerid
     * @return Companies
     */
    public function setOwnerid($ownerid)
    {
        $this->ownerid = $ownerid;
        return $this;
    }
    /**
     * Get ownerid
     *
     * @return integer 
     */
    public function getOwnerid()
    {
        return $this->ownerid;
    }
}

Stores.php 的一些基本代码

// AppBundle/Entity/Stores.php
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
/**
 * Stores
 *
 * @ORMTable(name="stores", uniqueConstraints={@ORMUniqueConstraint(name="branchOf", columns={"branchOf"})})
 * @ORMEntity
 */
class Stores
{
    /**
     * @var integer
     *
     * @ORMColumn(name="branchOf", type="integer", nullable=false)
     */
    private $branchof;
    /**
     * Set branchof
     *
     * @param integer $branchof
     * @return Stores
     */
    public function setBranchof($branchof)
    {
        $this->branchof = $branchof;
        return $this;
    }
    /**
     * Get branchof
     *
     * @return integer 
     */
    public function getBranchof()
    {
        return $this->branchof;
    }
}

您可以使用自定义注册表,但最好的方法显然是监听FOSUser发送的注册事件。

这里有一个例子:

class RegistrationListener implements EventSubscriberInterface
{
    /**
     * L'entity manager
     *
     * @var EntityManager
     */
    private $em;
    /**
     * Constructeur de l'EventListener
     *
     * @param DoctrineORMEntityManager $entityManager
     */
   public function __construct(EntityManager $entityManager)
    {
        $this->em = $entityManager;
    }
    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return array(
            FOSUserEvents::REGISTRATION_INITIALIZE => 'onRegistrationInit',
        );
    }
    /**
     * Triggered when FOSUserEvents::REGISTRATION_INITIALIZE is caught.
     *
     * @param FOSUserBundleEventUserEvent $userEvent
     */
    public function onRegistrationInit(UserEvent $userEvent)
    {
        $user = $userEvent->getUser();
        // Define your own logic there
    }
}

别忘了让这个监听器成为一项服务:

#services.yml
services:
    oe_user.registration:
        class: OrienteExpressUserBundleEventListenerRegistrationListener
        # arguments are optional but you still can need them 
        # so I let the EM as example which is an often used parameter
        arguments:
            entityManager: "@doctrine.orm.entity_manager"
        tags:
            - { name: kernel.event_subscriber }

您可以在这里找到FOSUser发送的事件的完整列表

此外,Symfony实体是对象的模型。也就是说,您需要明白,您不是在模型中使用id,而是使用对象。

您不应该在实体中使用$var->setUserId()之类的东西。原则是用来管理你们的关系的,所以要小心这一点。如果不使用Symfony&按照设计的方式行事。

编辑:

在您的公司实体中,您的关系介于"公司"one_answers"用户"对象之间。这意味着你的公司不需要用户id,只需要用户的一个实例。

我认为在想做高级的事情之前,你可能会回到基础。

用户和公司之间的关系不应该是由整数属性设计的,而应该是真正的原则关系。

例如:

class Company {
    /**
     * @ORMManyToOne(targetEntity="PathToUser")
     * @ORMJoinColumn(nullable=false)
     */
     private $owner;
     /**
      * @param $user User 
      */
     public function setUser(User $user)
     {
         $this->user = $user;
     }
}

然后你将创建一家新公司。你不需要知道用户的id,甚至不需要插入它就可以在它们之间建立链接。但是,如果你还没有意识到这一点,我认为你应该再次回到Symfony的基础知识,因为这是需要掌握的最重要的功能之一。

最新更新