【发布时间】:2016-01-29 10:14:24
【问题描述】:
我知道有类似的问题,但没有一个解决方案适用于 Symfony 3.x。
所以我有三个实体,用户、角色和权限。用户具有角色(多对多)和权限(也是多对多)。然后我有一个表单,虽然权限工作正常,但角色却不行。
我能看到的唯一区别是,返回角色的函数没有按照应有的方式调用 getRoles(?),因为具有此名称的函数必须返回字符串数组(而不是角色实体数组)才能满足预期AdvancedUserInterface,这就是为什么另一个函数 (getRoleEntities) 返回 $this->roles,但我相信我在构建表单时反映了它。
这是用户实体类的简化版本:
/**
* @ORM\Table(name="user")
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User implements AdvancedUserInterface, \Serializable {
//id, username, personalname, password, email and isactive ommited
/**
*
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Permission", cascade = {"persist"})
* @ORM\JoinTable(name="user_permission")
*/
private $permissions;//this works
/**
*
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Role", cascade = {"persist"})
* @ORM\JoinTable(name="user_role")
*/
private $roles;//this doesn't work
public function __construct() {
$this->permission = new ArrayCollection();
$this->roles = new ArrayCollection();
}
//irrelevant getters/setters ommited
/**
* Add Permission
*
* @param \AppBundle\Entity\Permission $userPermission
*
* @return User
*/
public function addPermission(\AppBundle\Entity\Permission $userPermission) {
$this->permissions[] = $userPermission;
return $this;
}
/**
* Remove Permission
*
* @param \AppBundle\Entity\Permission $userPermission
*/
public function removePermission(\AppBundle\Entity\Permission $userPermission) {
$this->permissions->removeElement($userPermission);
}
/**
* Get Permissions
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getPermissions() {
return $this->permissions;
}
////////////////////////////////
//roles
/**
* Add role
* @param \AppBundle\Entity\Role $role
*
* @return User
*/
public function addRoleEntity(\AppBundle\Entity\Role $role) {
$this->roles[] = $role;
return $this;
}
/**
* Remove role
* @param \AppBundle\Entity\Role $role
*/
public function removeRoleEntity(\AppBundle\Entity\Role $role) {
$this->roleRoles->removeElement($role);
}
/**
* I know this one should simply return $this->roles, but it has to return array of strings to meet expectations of the AdvancedUserInterface, that is why another function (getRoleEntities) returns $this->roles
* @return array
*/
public function getRoles() {
$ret_val = array();
$roles = $this->getRoleEntities();
if ($roles) {
foreach ($roles as $role) {
$ret_val[] = $role->getRoleName();
}
}
return $ret_val;
}
/**
* Get roles
*/
public function getRoleEntities() {
return $this->roles;
}
}
这是我构建表单的方式:
$em = $this->getDoctrine()->getManager();
$user = $em->find('AppBundle:User',1);//just for testing
$form = $this->createFormBuilder($user)
->add('personal_name', \Symfony\Component\Form\Extension\Core\Type\TextType::class, array('label' => 'Imię i nazwisko: '))
->add('is_active', \Symfony\Component\Form\Extension\Core\Type\CheckboxType::class, array('label' => 'Active: ','required' => false))
->add('permissions', \Symfony\Bridge\Doctrine\Form\Type\EntityType::class , array(
'class' => 'AppBundle\Entity\Permission',
'multiple' => true,
'expanded' => true
))
->add('roleEntities', \Symfony\Bridge\Doctrine\Form\Type\EntityType::class , array(
'class' => 'AppBundle\Entity\Role',
))
->add('save', \Symfony\Component\Form\Extension\Core\Type\SubmitType::class, array('label' => 'Save'))
->getForm();
当我打开一个页面时,我得到了这个异常:
既不是属性“roleEntities”也不是方法之一 "addRoleEntity()"/"removeRoleEntity()", "setRoleEntities()", “roleEntities()”、“__set()”或“__call()”存在并具有公共访问权限 在“AppBundle\Entity\User”类中。
ps。我标记了这个“symfony2”,因为 AFAIK 2.9 和 3.0 之间没有太大区别
【问题讨论】:
-
将您的字段命名为
roles而不是roleEntities。 -
但它被命名为“roles”,只是getter被命名为“getRolesEntieties” - 这是必要的,因为名为“getRoles”的函数必须返回一个字符串数组(而不是角色数组实体)来满足我实现的 AdvancedUserInterface 的期望,
-
在表单中,您必须将其命名为
roles,如果没有名为roleEntity的字段,则设置为mapped=false。 -
@malcom - 我可以从你的个人资料中看到,你对 Symfony 了解很多,但我认为你还没有阅读整个问题 :( 我不能做 mapped=false,因为我确实在数据库中的用户和角色之间有关系,ManyToMany。我确实希望它被编辑(修改)。但是好的,我将表单中的字段更改为“角色”并将实体类中的属性公开,希望 Symfony 将选择它,而不是尝试在实体类中调用 getRoles 函数(因为它必须返回字符串数组而不是 $roles 属性)。现在我有这个例外:
-
我还没有阅读整个问题,但我想通知您,您必须准确地命名表单字段,就像您在类属性中命名的那样。这样就可以正确映射。我不知道您为什么将角色用作独立实体(您以前是 drupal 开发人员吗?),而且我不知道 ORM(多年来我只使用 mongodb),所以我无法帮助您处理 ORM 映射。只是简单如果要添加表单字段,名称必须与类属性相同,否则必须设置
mapped = false。
标签: symfony-forms symfony