0

我有一个自定义处理程序,用于像实体这样的角色和多对多关系,如下所示:

<?php

namespace Digital\UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\Role\RoleInterface;


    /**
     * Role Entity
     *
     * @ORM\Entity
     * @ORM\Table( name="app_roles" )
     */
    class Role implements RoleInterface
    {

        /**
         * @ORM\Id
         * @ORM\Column(type="integer", name="id")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;

        /**
         * @ORM\Column(type="string", name="name", unique=true, length=100)
         */
        private $role;

        /**
         * @var Role
         * @ORM\ManyToOne(targetEntity="Role")
         * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
         **/
        private $parent;


        /**
         * @param $role
         */
        public function __construct($role)
        {
            $this->role = (string)$role;
        }


        /**
         * @return string
         */
        public function __toString()
        {
            return $this->role;
        }


        /**
         * @param $role
         */
        public function setRole($role)
        {
            $this->role = $role;
        }


        /**
         * @return string
         */
        public function getRole()
        {
            return $this->role;
        }


        /**
         * @param Role $parent
         *
         * @return $this
         */
        public function setParent(Role $parent)
        {
            $this->parent = $parent;
            return $this;
        }


        /**
         * @return Role
         */
        public function getParent()
        {
            return $this->parent;
        }


        /**
         * @return bool
         */
        public function hasParent()
        {
            return null !== $this->parent;
        }

    }

然后我将我的用户对象配置如下:

<?php
// src/Acme/UserBundle/Entity/User.php

namespace Digital\UserBundle\Entity;

use FOS\UserBundle\Entity\User as BaseUserOld;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use FOS\MessageBundle\Model\ParticipantInterface;
use Symfony\Component\HttpFoundation\File\File;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;

/**
 * @ORM\Entity
 * @ORM\Table(name="app_users")
 * @ORM\Entity(repositoryClass="Digital\UserBundle\EntityRepository\UserRepository")
 */
class User extends BaseUser implements ParticipantInterface
{
    // properties...


    /**
     * @ORM\ManyToMany(targetEntity="Role", indexBy="name")
     * @ORM\JoinTable(name="app_users_roles")
     */
    protected $roles;

    /**
     * Construct.
     */
    public function __construct()
    {
        parent::__construct();

        $this->roles       = new ArrayCollection;
    }


    /**
     * @return Role[]
     */
    public function getRoles()
    {
        $roles   = $this->getRolesCollection()->toArray();
        $roles[] = $this->getDefaultRole();
        return $roles;
    }


    /**
     * @param $role
     *
     * @return bool
     */
    public function hasRole($role)
    {
        if ($role instanceof Role) {
            $role = $role->getRole();
        }

        foreach ($this->getRoles() as $roleEntity) {
            if ($roleEntity->getRole() === $role) {
                return true;
            }
        }

        return false;
    }


    /**
     * @param $role
     *
     * @return self
     * @throws \InvalidArgumentException
     */
    public function addRole($role)
    {
        $this->normaliseRole($role);

        if ($this->hasRole($role)) {
            throw new \InvalidArgumentException("Role $role is already applied to this " . get_class($this));
        }

        $this->getRolesCollection()->add($role);

        return $this;
    }


    /**
     * @param Role|string $role
     *
     * @return self
     */
    public function removeRole($role)
    {
        $this->normaliseRole($role);
        $this->getRolesCollection()->removeElement($role);
        return $this;
    }


    /**
     * @param Role[]|string[] $roles
     *
     * @return self
     */
    public function setRoles(array $roles)
    {
        $this->getRolesCollection()->clear();

        foreach ($roles as $role) {
            $this->addRole($role);
        }

        return $this;
    }


    /**
     * {@inheritdoc}
     */
    protected function getRolesCollection()
    {
        return $this->roles;
    }


    /**
     * {@inheritdoc}
     */
    protected function getDefaultRole()
    {
        return new Role(parent::ROLE_DEFAULT);
    }


    /**
     * @param $role
     *
     * @throws \InvalidArgumentException
     */
    protected function normaliseRole(&$role)
    {
        if (is_string($role)) {
            $role = new Role($role);
        }

        if (!$role instanceof Role) {
            throw new \InvalidArgumentException('Role must be either a Role Entity or a string.');
        }
    }
}

现在我的问题是如何配置我的表单以根据界面接受对象数组?

我是否使用集合/实体/选择?一切似乎都失败了……

    $builder->add('roles', 'entity', array(
        'class' => 'Digital\UserBundle\Entity\Role',
        'by_reference' => true,)
    );

可捕获的致命错误:传递给 Digital\UserBundle\Entity\User::setRoles() 的参数 1 必须是数组类型,给定对象

任何提示将不胜感激......

这也不起作用:

    $builder->add('roles', 'collection', array(
        'type' => new RoleType(),
        'allow_add'    => true,
        'allow_delete' => true,
        'by_reference' => false,
    ));

或者:

    $builder->add('roles', 'collection', 
        array( 'options' => array(
            'data_class' => 'Digital\UserBundle\Entity\Role'),
            'allow_add' => true, 
            'allow_delete' => true, 
            'by_reference' => false));

我可以让它工作的壁橱是这样的:

    public function addRole($role)
    {
        $this->normaliseRole($role);

//        if (!$this->roles->contains($role)) {
        if (!$this->hasRole($role)) {
            $this->getRolesCollection()->add($role);
        }

        return $this;
    }

        $builder->add('roles', 'collection', array( 'options' => array('data_class' => 'Digital\UserBundle\Entity\Role'),
            'allow_add' => true, 'allow_delete' => true, 'by_reference' => false));

这样我就可以毫无错误地提交表单,但是任何更改都失败了,因为我必须添加级联持久性,并且这个角色已经在角色表中,并且学说正试图再次插入它...... ;(

4

2 回答 2

1

对此的回答是:

    $builder->add('rolesCollection', 'entity', array(
        'multiple'     => true,
        'expanded'     => true,
        'by_reference' => false,
        'label' => 'Roles',
        'class'        => 'Digital\UserBundle\Entity\Role',
    ));

并玩'rolesCollection'而不是'roles'。

/**
 * @param Collection $collection
 */
public function setRolesCollection($collection)
{
    $this->setRoles($collection->toArray());

    return $this;
}
于 2013-03-30T11:59:06.163 回答
0

您是否尝试过使用该collection类型?entity类型意味着一个相关的对象。

http://symfony.com/doc/current/cookbook/form/form_collections.html

于 2013-03-25T22:11:25.193 回答