我也有同样的问题,也使用注释。
注意:由于一些读者在将所有内容放在一起时遇到问题,我用我的 UserBundle 创建了一个 gitHub 存储库。如果您发现此 HowTo 中缺少某些内容,请告诉我,以便我添加。
这篇文章涵盖三个方面,基于 DB 的角色与树结构实现,框架配置也支持DB 角色的RoleHierarchy (getReachableRoles)。没有它,毕竟在 DB 中扮演角色是没有用的。并且Doctrine 订阅者在某些实体被持久化时创建角色。
FOS 必须做出的改变是深刻的,并且有据可查,但我必须说,一个HowTo Use
示例代码会阻止我阅读很多内容,(不是抱怨,至少我现在对编译器通行证有所了解。)
角色到数据库
我正在使用 Sf 2.4,但这应该从 2.3 开始工作。这是我的解决方案涉及的文件,每个文件考虑一个步骤:
./:
composer.json
src/Application/UsuarioBundle/:
ApplicationUsuarioBundle.php
src/Application/UsuarioBundle/Resources/config/doctrine/model/:
User.orm.xml
src/Application/UsuarioBundle/Entity/:
Role.php Usuario.php
在copmoser.json
我升级的学说包中,它包含所需的文件:
"require": {
...
"doctrine/doctrine-bundle": "~1.3@dev",
...
}
在Bundle.php
文件中,您必须注册编译器通行证
namespace Application\UsuarioBundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;
class ApplicationUsuarioBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$mappings = array(
realpath(__DIR__ . '/Resources/config/doctrine/model') => 'FOS\UserBundle\Model',
realpath(__DIR__ . '/Resources/config/doctrine/model') => 'FOS\UserBundle\Entity',
);
$container->addCompilerPass(
DoctrineOrmMappingsPass::createXmlMappingDriver(
$mappings, array('fos_user.model_manager_name'), false
)
);
}
这是新版本的学说包导入的依赖:
`\Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass`.
我假设这个映射信息是在 FOSUSerBundle 之后添加的,因为我只是重复了我在 FOSUerBundle.php 中看到的过程(仅针对 ORM 进行了简化),希望它优先并且确实如此。
中的映射是注释掉的第 35 行User.orm.xml
的精确副本。这将删除映射超类中角色的冲突映射。./vendor/friendsofsymfony/user-bundle/FOS/UserBundle/Resources/config/doctrine/model/User.orm.xml
<!--<field name="roles" column="roles" type="array" />-->
从现在开始,你只需做你想做的第一件事,实现你对角色的想法。这是我的:扩展 FOS\UserBundle\Model\User 的用户类,但现在使用您在包中使用的映射。
src/Application/UsuarioBundle/Entity/Role.php
和角色类:
src/Application/UsuarioBundle/Entity/Usuario.php
完成后,您可以看到正确的 SQL 更改由 schema update --dump-sql 转储。
$ php app/console doctrine:schema:update --dump-sql --complete
CREATE TABLE fos_usuario_role (usuario_id INT NOT NULL, role_id INT NOT NULL, INDEX IDX_6DEF6B87DB38439E (usuario_id), INDEX IDX_6DEF6B87D60322AC (role_id), PRIMARY KEY(usuario_id, role_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE fos_role (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(30) NOT NULL, role VARCHAR(20) NOT NULL, UNIQUE INDEX UNIQ_4F80385A57698A6A (role), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
ALTER TABLE fos_usuario_role ADD CONSTRAINT FK_6DEF6B87DB38439E FOREIGN KEY (usuario_id) REFERENCES fos_user (id) ON DELETE CASCADE;
ALTER TABLE fos_usuario_role ADD CONSTRAINT FK_6DEF6B87D60322AC FOREIGN KEY (role_id) REFERENCES fos_role (id) ON DELETE CASCADE;
ALTER TABLE fos_user DROP roles;
尽管如此,我并不代表我需要的角色层次结构。
希望它对某人有用。我确定您已经解决了这个问题,或者失去了工作:p。
我遵循的文档:
https://github.com/symfony/symfony/pull/7599
https://github.com/FriendsOfSymfony/FOSUserBundle/pull/1081
http://symfony.com/doc/2.4/cookbook/doctrine/mapping_model_classes.html
http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html
角色层次实现
解决方案中涉及的文件:
// The Magician, for I just re-instantiated RoleHierarchyVoter & ExpressionVoter
// classes as ApplicationUsuarioBundle services; passing my RoleHierarchy
// implementation.
src/Application/UsuarioBundle/Role/RoleHierarchy.php
// duplicating security.access.expression_voter &&
// application_usuario.access.role_hierarchy_voter BUT WITH NEW
// RoleHierarchy ARGUMENT
src/Application/UsuarioBundle/Resources/config/services.xml
// Entities, important methods are collection related
src/Application/UsuarioBundle/Entity/Role.php
src/Application/UsuarioBundle/Entity/Usuario.php
// Edited, commented out regular hardcoded roleHierarchy
app/config/security.yml
// CRUD related, sample files will add dependencies to lexik/form-filter-bundle;
// docdigital/filter-type-guesser; white-october/pagerfanta-bundle
src/Application/UsuarioBundle/Controller/RoleController.php
src/Application/UsuarioBundle/Form/RoleType.php
src/Application/UsuarioBundle/Resources/views/Role/edit.html.twig
src/Application/UsuarioBundle/Resources/views/Role/index.html.twig
src/Application/UsuarioBundle/Resources/views/Role/new.html.twig
src/Application/UsuarioBundle/Resources/views/Role/show.html.twig
你可以在这个 gist中看到文件
或者直接访问每个文件(因为 Gist 不保留列表顺序)。
src/Application/UsuarioBundle/Role/RoleHierarchy.php
src/Application/UsuarioBundle/Resources/config/services.xml
src/Application/UsuarioBundle/Entity/Role.php
src/Application/UsuarioBundle/Entity/Usuario.php
应用程序/配置/security.yml
src/Application/UsuarioBundle/Controller/RoleController.php
src/Application/UsuarioBundle/Form/RoleType.php
src/Application/UsuarioBundle/Resources/views/Role/edit.html.twig
文档如下:
食谱:安全选民
组件:安全性
参考:服务标签优先级
来源:RoleHierarchyInterface
教义订阅者
你会走到这一步才能意识到缺少一些东西......
我将 Roles 移植到 DB 的主要原因是因为我正在处理一个动态的(从结构的角度来看)应用程序,它使用户能够配置工作流。当我添加一个新区域,一个新流程,一个新活动(或更新名称或父子关系,或删除任何)时,我需要生成新角色automatically
。
然后你会想到 LyfeCycleEvents 的 Doctrine 订阅者,但在 PrePersist/PreUpdate 中添加新实体将需要嵌套刷新,在我的情况下这会搞砸,当你只需要更新已经“computedChanges”实体上的一些字段时会更容易。
所以我用来挂钩和创建/编辑/删除角色的是 onFlush,此时 computChangeSet() 可以很好地添加新实体。
我将以ProcessRolesSubscriber Gist为例。