Symfony ACL => ObjectIdentity()已与ACL关联

时间:2012-12-09 02:37:28

标签: symfony acl symfony-2.1 fixtures

我想在Symfony 2中使用ACL并将其加载到我的灯具中。

以下代码完美无缺,但如果我取消注释array('myprivateroom', 'user1', 'view'),,我会收到以下错误:

[Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException]  ObjectIdentity(1, Acme\RoomBundle\Entity\Room) is already associated with an ACL.

我认为问题出在$acl = $aclProvider-createAcl(ObjectIdentity::fromDomainObject($room));,但我不知道如何解决。

public function load(ObjectManager $manager)
{
    $datas = array(
        array('myprivateroom', 'admin', 'owner'),
        //array('myprivateroom', 'user1', 'view'),
        array('mypublicroom', 'user1', 'owner'),
    );

    foreach ($datas as $data) {
        // creating the ACL
        $room = $this->getReference($data[0]);
        $aclProvider = $this->container->get('security.acl.provider');
        $objectIdentity = ObjectIdentity::fromDomainObject($room);
        //problem here when I uncomment array('myprivateroom', 'user1', 'view'),
        $acl = $aclProvider->createAcl(ObjectIdentity::fromDomainObject($room));

        // retrieving the security identity of the user
        $user = $this->getReference($data[1]);
        $securityIdentity = UserSecurityIdentity::fromAccount($user);

        //create mask
        $builder = new MaskBuilder();
        $builder->add($data[2]);
        $mask = $builder->get();

        // grant owner access
        $acl->insertObjectAce($securityIdentity, $mask);
        $aclProvider->updateAcl($acl);
    }
}

感谢

更新: 如果我做2个数组,如

$datas = array(
    array('myprivateroom', 'admin', 'owner'),
    array('mypublicroom', 'user1', 'owner'),
);

$datas2 = array(
    array('myprivateroom', 'user1', 'view'),
);

还有2个foreach但是,在第二个中,我将$acl = $aclProvider->createAcl(ObjectIdentity::fromDomainObject($room));替换为$acl = $aclProvider->findAcl($objectIdentity);,它完美无缺,但我不认为这是正确的方法,以下内容不起作用。

try {
    $acl = $aclProvider->findAcl($objectIdentity);
} catch (AclNotFoundException $e) {
    $acl = $aclProvider->createAcl($objectIdentity);
}

2 个答案:

答案 0 :(得分:4)

我和你有完全相同的问题,我已经解决了这个问题。

try {
    $acl = $this->get('security.acl.provider')->findAcl($idObjeto);
} catch (\Symfony\Component\Security\Acl\Exception\AclNotFoundException $e) {
    $acl = $this->get('security.acl.provider')->createAcl($idObjeto);
}

我没有解释为什么。唯一不同的是" \ Symfony \ Component \ Security \ Acl \ Exception \ AclNotFoundException"

答案 1 :(得分:0)

我迟到了,但万一有人需要了解您的代码发生了什么。如果循环遍历此数组:

$datas = array(
    array('myprivateroom', 'admin', 'owner'),
    array('myprivateroom', 'user1', 'view'),
    array('mypublicroom', 'user1', 'owner'),
);

您将使用:

 $acl = $aclProvider->createAcl(ObjectIdentity::fromDomainObject($room));

在第一个和第二个循环上。它将尝试两次为'myprivateroom'创建访问控制列表(ACL)。这就是为什么它会抛出一个错误,说明你已经拥有了这个Room实体的列表。

ObjectIdentity(1, Acme\RoomBundle\Entity\Room) is already associated with an ACL

解决问题的一个好方法是尝试它是否有ACL,如果它没有,则创建它(由@JGrinon提供答案)。否则,您可以在多维数组中组织数据并循环遍历它:

// PHP array but you could use a JSON array to be clearer
$datas = array(
    array('myprivateroom',
        array(
            array('admin', 'owner'),
            array('user1', 'view1')
        )
    ),
    array('mypublicroom',
        array(
            array('user1', 'owner'),
        )
    ),
);

// Call ACL Provider service before the loop
$aclProvider = $this->container->get('security.acl.provider');

// Loop through the array
foreach ($datas as $data) {
    // Get the room name
    $room = $this->getReference($data[0]);
    $objectIdentity = ObjectIdentity::fromDomainObject($room);
    // The list is created only once for each room
    $acl = $aclProvider->createAcl(ObjectIdentity::fromDomainObject($room));

    // Loop through the list of users and associated rights
    $list = $this->getReference($data[1]);
    foreach ($list as $row) {
        // Retrieving the security identity of the user
        $user = $row[0];
        $securityIdentity = UserSecurityIdentity::fromAccount($user);

        // Create Mask
        $builder = new MaskBuilder();
        $builder->add($row[1]);
        $mask = $builder->get();

        // Grant access
        $acl->insertObjectAce($securityIdentity, $mask);
    };

    // Update Access Control List
    $aclProvider->updateAcl($acl);
}

希望这会有所帮助;)