Reputation: 867
I know there are similar questions, but none of the solutions work for Symfony 3.x.
So I have three entities, User, Role and Permission. User has Roles (ManyToMany) and Permissions (also ManyToMany). And then I have a form, and while Permissions work fine, Roles do not.
The only difference I can see, is that a function returning roles isn't called getRoles as it should(?), because a function with this name has to return array of strings (not array of role entities) to meet expectations of the AdvancedUserInterface, that is why another function (getRoleEntities) returns $this->roles, but I believe I reflected it while building a form.
Here is a shortened version of the User entity class:
/**
* @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;
}
}
And here is how I build a form:
$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();
And when I'm opening a page I get this exception:
Neither the property "roleEntities" nor one of the methods "addRoleEntity()"/"removeRoleEntity()", "setRoleEntities()", "roleEntities()", "__set()" or "__call()" exist and have public access in class "AppBundle\Entity\User".
ps. I tagged this "symfony2", because AFAIK there are no big differences between 2.9 and 3.0
Upvotes: 1
Views: 655
Reputation: 867
OK, fortunately guys from #Symfony irc, helped me, there are a few issues there:
functions like addRoleEntity should rather be called after the variable, e.g. addRole
Like @malcom mentioned, while building the form, instead of:
->add('roleEntities', \Symfony\Bridge\Doctrine\Form\Type\EntityType::class , array( 'class' => 'AppBundle\Entity\Role',
It should be:
->add('roles', \Symfony\Bridge\Doctrine\Form\Type\EntityType::class , array(
'class' => 'AppBundle\Entity\Role',
'multiple' => true,
)
Because this is how the variable is named. Plus, since this is ManyToMany I also added 'multiple' => true, otherwise it did save, but incorectly loaded this information.
3.It went further, and a new error appeared: Can not read the choices from the choice list.
I changed the body of the getRoles method to:
return $this->roles->toArray();
And it worked.
The last idea is mine, not from the IRC, I'm saying this, because I don't like this solution. If it is a bad solution, then it's my fault.
Upvotes: 0