使用 FosUserBundle 创建管理员用户

Posted

技术标签:

【中文标题】使用 FosUserBundle 创建管理员用户【英文标题】:Create an Admin User with FosUserBundle 【发布时间】:2014-03-12 16:58:49 【问题描述】:

我尝试使用以下命令从命令窗口使用 FOsUserBundle 创建一个管理员用户:

php app/console fos:user:create

在我的项目中,管理员用户以强制性的方式扩展了其他用户。所以,当我选择我的用户名、邮箱和密码时,它会告诉我:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'latitude' cannot be null

如何在我的 AdminUser 中设置值“纬度”?我也使用 PUGXMultiUserBundle。

【问题讨论】:

您是否尝试在声明时将属性设置为默认值?类似“私人 $latitude = 0”的东西。当然这不是最优的,因为它不是一个真正有用的默认值。但我想如果你想使用 fos:user:create 命令,除了设置默认值之外,你别无选择。如果这不是您想要的,我想您必须创建自己的用户创建命令,这应该不会太难。 @Leif 我会避免设置默认值。如何创建我的用户创建命令?我在哪里可以找到文档? 【参考方案1】:

对我来说,唯一可能的方法是

1 - 覆盖 FOSUserBundle 的 cli 命令放入 Command/CreateUserCommand.php 2 - 覆盖FOSUserBundle的用户创建方法放入Util/UserManipulator.php

// Command/CreateUserCommand.php
protected function execute(InputInterface $input, OutputInterface $output)

  $username   = $input->getArgument('username');
  $email      = $input->getArgument('email');
  $password   = $input->getArgument('password');
  $inactive   = $input->getOption('inactive');
  $superadmin = $input->getOption('super-admin');
  $latitude   = $input->getOption('latitude'); //this will be your own logic add

  $manipulator = $this->getContainer()->get('fos_user.util.user_manipulator');
  $manipulator->create($username, $password, $email, $latitude, !$inactive, $superadmin);

  $output->writeln(sprintf('Created user <comment>%s</comment>', $username));

// Util/UserManipulator.php
public function create($username, $password, $email, $latitude, $active, $superadmin)

  $user = $this->userManager->createUser();
  $user->setUsername($username);
  $user->setEmail($email);
  $user->setPlainPassword($password);
  $user->setEnabled((Boolean) $active);
  $user->setSuperAdmin((Boolean) $superadmin);
  $user->setLatitude($latitude);
  $this->userManager->updateUser($user);

  return $user;
 

当然,当我说覆盖时,我的意思是...覆盖:P 所以你不必修改 FOSUserBundle 原始文件(你知道,这很危险,原因有很多),而是通过让你的包扩展来制作你自己的文件FOSUserBundle

您想知道如何通过 FOSUserBundle 扩展您的捆绑包吗?

进入你的包“主文件” - 是你用来注册你的包的那个 - 只需添加这行

public function getParent()

  return 'FOSUserBundle';

然后你只需重新创建你的 ovverride 文件所在的树结构到原始包中,到你的自定义包的 Resources/ 目录(相同的位置,相同的文件名,相同的注释,如果有的话)和....魔法可以start :)仅对view有效,请注意!

“覆盖”是什么意思?

Override 意味着您采用现有函数,通过在其他地方重新定义来“隐藏”它(声明一个具有相同名称的函数,无论它接受多少参数,无论参数类型如何,因为 php 不支持方法重载[除非你做了一些“破解”])然后你可以使用它而不是原来的。这是向函数添加额外功能或更改函数本身的常用技术。 假设我们有两个类 A 和 B,其中 B 是 A 的子类。还假设 A 有一个名为 myMethod() 的方法。

在 B 中我们可以做类似的事情

public function myMethod() 
  parent::myMethod();
  //add extra functionalities here

通过这种方式,我们在调用父(“原始”)方法时添加额外的功能,然后执行一些额外的功能

如果在 B 中我们制作类似的东西

公共函数 myMethod() //这里有一些代码,但没有调用父方法

我们正在重新定义 myMethod() 的行为

Symfony2 如何让我覆盖方法?

正如我之前在回答中所说,您必须使您的包成为包含您尝试覆盖的函数的包的子包(在这种情况下为FOSUserBundle)。一旦你这样做了,使用你的包的Resources目录来完成你需要的。复制原始包的“树文件夹结构”(即:文件夹的相同名称)直到你到达包含你需要重写的函数的类。

按照您的实际示例:您需要覆盖 Command/CreateUserCommand.php 中包含的 execute() 函数。您必须在您的捆绑文件夹中创建该路径:

PathTo/YourCostumBundle/Command/

并将上面我向您展示的内容放入文件CreateUserCommand.php

如果您不明白我在哪里找到该路径,请查看FOSUserBundle 代码,它绝对清楚!

为什么直接修改 FOSUserBundle 代码很危险?

好吧,我可以向您展示一个批评点的很多答案。选择主要的(不按重要性排序):

如果您需要更新 FOSUserBundle 怎么办?您将使用 composer 并丢失您对 FOSUserBundle 代码所做的所有修改 如果您的项目中有多个捆绑包需要使用 FOSUserBundle,该怎么办?也许自定义行为对一个捆绑包有意义,但对另一个捆绑包没有意义。在本地捆绑包级别定制行为有助于您保持 FOSUserBundle 逻辑完整 如果您正在开发一个想要与其他用户共享的捆绑包怎么办?您需要强制他们“采用”您自己定制的 FOSUserBundle 版本,并警告他们不要更新它

最后:我完全知道您的实体没有进入 FOSUserBundle,但我敢打赌他们扩展了 FOSUserBundle 基本用户,所以我上面所说的适用于您的情况。

希望现在不那么模糊了 :)


文档:http://symfony.com/doc/current/cookbook/bundles/inheritance.html#overriding-controllers

【讨论】:

非常感谢您的帮助。我对 Symfony 和 php 很陌生,所以当你说“覆盖”时我不明白。为什么修改 FOSUserBundle 很危险?好吧,问题是:我应该改变什么?现在我使用 FosUserBundle 和 PUGXMultiUserBundle,我的 User 实体不在 FOSUserBundle 中,而是在 UserBundle 中,并且由两种不同类型的实体(如 user1 和 user2)扩展。 嗨!我还有一个疑问。我按照你告诉我的做(我创建了一个 Acme\MainBundle\Resources\FOSUserBundle\Command\CreateUserCommand.php 和一个 Acme\MainBundle\Resources\FOSUserBundle\Util\UserManipulator.php 文件并将父声明放入 \Acme\MainBundle\ AcmeMainBundle.php)。我清除了缓存,但 cmd 命令仍然没有询问我的纬度。我哪里错了?我从 MainBundle 调用命令而不是直接从 FOSUserBundle 调用命令的 cmd 怎么能? 我设法覆盖了模板系统,创建了Acme\MainBundle\Resources\views\layout.html.twig file;不将“FOSUserBundle”文件夹“添加”到主包中。我还尝试将protected function configure() 更改为 CreateUserCommand.php 添加new InputArgument('latitude', InputArgument::REQUIRED, 'Latitude') 嗨@GianniAlessandro:你想知道系统现在可以调用什么命令吗?这很简单:是 Symfony2 的逻辑。不知道为什么您的命令仍然无法正常工作,但我确信我向您提出的建议是完成您在此处提出的要求的正确方法。而且我确信我在我的项目中做了类似的事情,并且还阅读了文档;-) @GianniAlessandro:嗨,詹尼。我犯了一个错误。现在我检查了我的 proget,我看到只有视图被 Resources 文件夹覆盖。对于覆盖控制器,只需将三文件夹结构直接重新创建到您的包主文件夹中。如果对您有意义,请参阅我的答案中的更新,请让我更新。【参考方案2】:

我总是遵循我在 symfony 文档中学到的模式:

php bin/console fos:user:create usertest mail@domain.com password

有时我需要更改表“fos_user”上的“roles

然后

a:0:

a:1:i:0;s:10:"ROLE_ADMIN";

【讨论】:

【参考方案3】:

创建用户后:

bash-5.1# bin/console fos:user:create admin admin@mydomain.com password123

提升具有 ROLE_ADMIN 角色的用户:

bash-5.1# bin/console fos:user:promote
Please choose a username:admin
Please choose a role:ROLE_ADMIN
Role "ROLE_ADMIN" has been added to user "admin". This change will not 
apply until the user logs out and back in again.

【讨论】:

以上是关于使用 FosUserBundle 创建管理员用户的主要内容,如果未能解决你的问题,请参考以下文章

在 FOSUserBundle 中管理用户/角色/组

使用 FOSUserBundle 创建新用户失败

使用 FosUserBundle symfony2 管理多个角色

在 FOSUserBundle 中清除组和角色的使用

FOSUserBundle 未配置编码器:创建新用户

FOSUserBundle 在 EasyAdminBundle 中管理((“用户”实体必须使用“类”选项定义其关联的 Doctrine 实体类))Symfony