我有一个自定义处理程序,用于像实体这样的角色和多对多关系,如下所示:
<?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));
这样我就可以毫无错误地提交表单,但是任何更改都失败了,因为我必须添加级联持久性,并且这个角色已经在角色表中,并且学说正试图再次插入它...... ;(