Doctrine\ORM\Mapping\MappingException Duplicate definition of column 'username' on entity - php

I am using FOSUserBundle but I wanted to rename the roles field column name to user_roles for legacy database,
By referring to
https://github.com/FriendsOfSymfony/FOSUserBundle/issues/338
and
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/doctrine.md#replacing-the-mapping-of-the-bundle
I am trying to overwrite the existing FOS\UserBundle\Model\User with my AcmeDemoBundle:User entity by mapping all fields again.
This is my Class,
PLEASE NOTE I AM EXTENDING ENTITY DIRECTLY FROM "FOS\UserBundle\Model\User"
namespace Acme\SecurityBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Acme\CommonBundle\Util\Url as Url;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Acme\SecurityBundle\Entity\UserRepository")
*/
Class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #ORM\Column(name="username", type="string", length=255)
*/
protected $username;
/**
* #var string
* #ORM\Column(name="username_canonical", type="string", length=255, unique=true)
*/
protected $usernameCanonical;
/**
* #var string
* #ORM\Column(name="email", type="string", length=255)
*/
protected $email;
/**
* #var string
* #ORM\Column(name="email_canonical", type="string", length=255, unique=true)
*/
protected $emailCanonical;
/**
* #var boolean
* #ORM\Column(name="enabled", type="boolean")
*/
protected $enabled;
/**
* The salt to use for hashing
*
* #var string
* #ORM\Column(name="salt", type="string")
*/
protected $salt;
/**
* Encrypted password. Must be persisted.
*
* #var string
* #ORM\Column(name="password", type="string")
*/
protected $password;
/**
* Plain password. Used for model validation. Must not be persisted.
*
* #var string
*/
protected $plainPassword;
/**
* #var \DateTime
* #ORM\Column(name="last_login", type="datetime", nullable=true)
*/
protected $lastLogin;
/**
* Random string sent to the user email address in order to verify it
*
* #var string
* #ORM\Column(name="confirmation_token", type="string", nullable=true)
*/
protected $confirmationToken;
/**
* #var \DateTime
* #ORM\Column(name="password_requested_at", type="datetime", nullable=true)
*/
protected $passwordRequestedAt;
/**
* #var Collection
*/
protected $groups;
/**
* #var boolean
* #ORM\Column(name="locked", type="boolean")
*/
protected $locked;
/**
* #var boolean
* #ORM\Column(name="expired", type="boolean")
*/
protected $expired;
/**
* #var \DateTime
* #ORM\Column(name="expires_at", type="datetime", nullable=true)
*/
protected $expiresAt;
/**
* #var array
* #ORM\Column(name="fos_roles", type="array", nullable=true)
*/
protected $roles;
/**
* #var boolean
* #ORM\Column(name="credentials_expired", type="boolean")
*/
protected $credentialsExpired;
/**
* #var \DateTime
* #ORM\Column(name="credentials_expire_at", type="datetime", nullable=true)
*/
protected $credentialsExpireAt;
public function __construct()
{
parent::__construct();
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
$this->enabled = false;
$this->locked = false;
$this->expired = false;
$this->roles = array();
$this->credentialsExpired = false;
//$this->setEmailHash();
}
public function addRole($role)
{
$role = strtoupper($role);
if ($role === static::ROLE_DEFAULT) {
return $this;
}
if (!in_array($role, $this->roles, true)) {
$this->roles[] = $role;
}
return $this;
}
/**
* Serializes the user.
*
* The serialized data have to contain the fields used by the equals method and the username.
*
* #return string
*/
public function serialize()
{
return serialize(array(
$this->password,
$this->salt,
$this->usernameCanonical,
$this->username,
$this->expired,
$this->locked,
$this->credentialsExpired,
$this->enabled,
$this->id,
));
}
/**
* Unserializes the user.
*
* #param string $serialized
*/
public function unserialize($serialized)
{
$data = unserialize($serialized);
// add a few extra elements in the array to ensure that we have enough keys when unserializing
// older data which does not include all properties.
$data = array_merge($data, array_fill(0, 2, null));
list(
$this->password,
$this->salt,
$this->usernameCanonical,
$this->username,
$this->expired,
$this->locked,
$this->credentialsExpired,
$this->enabled,
$this->id
) = $data;
}
/**
* Removes sensitive data from the user.
*/
public function eraseCredentials()
{
$this->plainPassword = null;
}
/**
* Returns the user unique id.
*
* #return mixed
*/
public function getId()
{
return $this->id;
}
public function getUsername()
{
return $this->username;
}
public function getUsernameCanonical()
{
return $this->usernameCanonical;
}
public function getSalt()
{
return $this->salt;
}
public function getEmail()
{
return $this->email;
}
public function getEmailCanonical()
{
return $this->emailCanonical;
}
/**
* Gets the encrypted password.
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
public function getPlainPassword()
{
return $this->plainPassword;
}
/**
* Gets the last login time.
*
* #return \DateTime
*/
public function getLastLogin()
{
return $this->lastLogin;
}
public function getConfirmationToken()
{
return $this->confirmationToken;
}
/**
* Returns the user roles
*
* #return array The roles
*/
public function getRoles()
{
$roles = $this->roles;
foreach ($this->getGroups() as $group) {
$roles = array_merge($roles, $group->getRoles());
}
// we need to make sure to have at least one role
$roles[] = static::ROLE_DEFAULT;
return array_unique($roles);
}
/**
* Never use this to check if this user has access to anything!
*
* Use the SecurityContext, or an implementation of AccessDecisionManager
* instead, e.g.
*
* $securityContext->isGranted('ROLE_USER');
*
* #param string $role
*
* #return boolean
*/
public function hasRole($role)
{
return in_array(strtoupper($role), $this->getRoles(), true);
}
public function isAccountNonExpired()
{
if (true === $this->expired) {
return false;
}
if (null !== $this->expiresAt && $this->expiresAt->getTimestamp() < time()) {
return false;
}
return true;
}
public function isAccountNonLocked()
{
return !$this->locked;
}
public function isCredentialsNonExpired()
{
if (true === $this->credentialsExpired) {
return false;
}
if (null !== $this->credentialsExpireAt && $this->credentialsExpireAt->getTimestamp() < time()) {
return false;
}
return true;
}
public function isCredentialsExpired()
{
return !$this->isCredentialsNonExpired();
}
public function isEnabled()
{
return $this->enabled;
}
public function isExpired()
{
return !$this->isAccountNonExpired();
}
public function isLocked()
{
return !$this->isAccountNonLocked();
}
public function isSuperAdmin()
{
return $this->hasRole(static::ROLE_SUPER_ADMIN);
}
public function isUser(\FOS\UserBundle\Model\UserInterface $user = null)
{
return null !== $user && $this->getId() === $user->getId();
}
public function removeRole($role)
{
if (false !== $key = array_search(strtoupper($role), $this->roles, true)) {
unset($this->roles[$key]);
$this->roles = array_values($this->roles);
}
return $this;
}
public function setUsername($username)
{
$this->username = $username;
return $this;
}
public function setUsernameCanonical($usernameCanonical)
{
$this->usernameCanonical = $usernameCanonical;
return $this;
}
/**
* #param \DateTime $date
*
* #return User
*/
public function setCredentialsExpireAt(\DateTime $date = null)
{
$this->credentialsExpireAt = $date;
return $this;
}
/**
* #param boolean $boolean
*
* #return User
*/
public function setCredentialsExpired($boolean)
{
$this->credentialsExpired = $boolean;
return $this;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function setEmailCanonical($emailCanonical)
{
$this->emailCanonical = $emailCanonical;
return $this;
}
public function setEnabled($boolean)
{
$this->enabled = (Boolean) $boolean;
return $this;
}
/**
* Sets this user to expired.
*
* #param Boolean $boolean
*
* #return User
*/
public function setExpired($boolean)
{
$this->expired = (Boolean) $boolean;
return $this;
}
/**
* #param \DateTime $date
*
* #return User
*/
public function setExpiresAt(\DateTime $date = null)
{
$this->expiresAt = $date;
return $this;
}
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function setSuperAdmin($boolean)
{
if (true === $boolean) {
$this->addRole(static::ROLE_SUPER_ADMIN);
} else {
$this->removeRole(static::ROLE_SUPER_ADMIN);
}
return $this;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
return $this;
}
public function setLastLogin(\DateTime $time = null)
{
$this->lastLogin = $time;
return $this;
}
public function setLocked($boolean)
{
$this->locked = $boolean;
return $this;
}
public function setConfirmationToken($confirmationToken)
{
$this->confirmationToken = $confirmationToken;
return $this;
}
public function setPasswordRequestedAt(\DateTime $date = null)
{
$this->passwordRequestedAt = $date;
return $this;
}
/**
* Gets the timestamp that the user requested a password reset.
*
* #return null|\DateTime
*/
public function getPasswordRequestedAt()
{
return $this->passwordRequestedAt;
}
public function isPasswordRequestNonExpired($ttl)
{
return $this->getPasswordRequestedAt() instanceof \DateTime &&
$this->getPasswordRequestedAt()->getTimestamp() + $ttl > time();
}
public function setRoles(array $roles)
{
$this->roles = array();
foreach ($roles as $role) {
$this->addRole($role);
}
return $this;
}
/**
* Gets the groups granted to the user.
*
* #return Collection
*/
public function getGroups()
{
return $this->groups ? : $this->groups = new ArrayCollection();
}
public function getGroupNames()
{
$names = array();
foreach ($this->getGroups() as $group) {
$names[] = $group->getName();
}
return $names;
}
public function hasGroup($name)
{
return in_array($name, $this->getGroupNames());
}
public function addGroup(\FOS\UserBundle\Model\GroupInterface $group)
{
if (!$this->getGroups()->contains($group)) {
$this->getGroups()->add($group);
}
return $this;
}
public function removeGroup(\FOS\UserBundle\Model\GroupInterface $group)
{
if ($this->getGroups()->contains($group)) {
$this->getGroups()->removeElement($group);
}
return $this;
}
public function __toString()
{
return (string) $this->getUsername();
}
}
If I remove extends BaseUser (FOS\UserBundle\Model\User), it gives error "The user provider must return a UserInterface object."
Then I tried adding "implements UserInterface, GroupableInterface" but it still gives "There is no user provider for user "Acme\SecurityBundle\Entity\User".

https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Model/User.php
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/config/doctrine/model/User.orm.xml
The property username is already defined in FOS\UserBundle\Model\User. Its metadata is in their resources config. So you are defining that column twice essentially.

We dont need to overwrite all fields to rename the field in database, I could achieve this by using AttributeOverride
/**
* #ORM\Entity
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Acme\SecurityBundle\Entity\UserRepository")
* #ORM\AttributeOverrides({
* #ORM\AttributeOverride(name="roles",
* column=#ORM\Column(
* name = "user_roles",
* type = "array"
* )
* )
* })
*/
Class User extends BaseUser
{
...
}

#Fosculus: what about the property id? It's also defined in FOS\UserBundle\Model\User. Why doesn't it give any problem?

Related

Datas overwriting problem with EntityType (same problem with ChoiceType) in Symfony 5

So here is my concern. I have a "Child" entity that contains $services and $users linked in ManyToMany.
The goal in my application is to be able to assign a child to a user of my service.
So, depending on the service I'm in, I won't have the same choice of users to assign.
In my ChildType, in my "users" field, I added a key ''query_builder'' that will retrieve only the users concerned.
My ChildType.php
<?php
namespace App\Form;
use App\Entity\Child;
use App\Entity\Service;
use App\Entity\Sexe;
use App\Entity\User;
use App\Repository\ServiceRepository;
use App\Repository\UserRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Security;
class ChildType extends AbstractType
{
/** #var User $user */
private $user;
private $serviceRepository;
private $authorization;
public function __construct(Security $security, AuthorizationCheckerInterface $authorization, ServiceRepository $serviceRepository)
{
$this->user = $security->getUser();
$this->authorization = $authorization;
$this->serviceRepository = $serviceRepository;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
/** #var Service $service */
$service = $this->user->getService();
$builder
->add('nom', TextType::class)
->add('prenom', TextType::class)
->add('sexe', EntityType::class, [
'class' => Sexe::class,
])
->add('dateDeNaissance', DateType::class, [
'widget' => 'single_text'
])
->add('lieuDeNaissance', TextType::class)
->add('nationalite', TextType::class)
->add('dateElaborationPpe', DateType::class, [
'widget' => 'single_text'
]);
if ($this->authorization->isGranted('ROLE_ADMIN')) {
$builder->add('users', EntityType::class, [
'class' => User::class,
'label' => 'Affecter à un utilisateur',
'query_builder' => function (UserRepository $userRepository) use ($service) {
return $userRepository->findByCurrentService($service);
},
'multiple' => true,
'expanded' => true,
]);
$builder->add('services', EntityType::class, [
'class' => Service::class,
'label' => 'Affecter à un service',
'choices' => $this->serviceRepository->findByDepartement($service->getDepartement()),
'choice_attr' => function($key, $val, $index) use ($service) {
return([]);
return $key->getCategorie()->getId() === $service->getCategorie()->getId() ?
['disabled' => 'disabled'] :
[];
},
'multiple' => true,
'expanded' => true,
]);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Child::class,
]);
}
}
The problem:
Let's assume that my Service #1 has several users from Service #1 to my child. When I assign in my Service #2 users from Service #2 to the child, I have my 2 new users from Service #2 in the database, but on the other hand, those from Service #1 have been deleted, which is not the desired behavior.
I've been looking for a topic for almost 2 hours, and I can't find an answer, so if it's a duplicate, really sorry.
edit method in my controller:
/**
* #Route("/{id}/edit", name="child_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Child $child): Response
{
$this->denyAccessUnlessGranted("edit", $child);
$form = $this->createForm(ChildType::class, $child);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('child_show', ['id' => $child->getId()]);
}
return $this->render('child/edit.html.twig', [
'child' => $child,
'form' => $form->createView(),
]);
}
User.php:
<?php
namespace App\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use App\Entity\Service;
use App\Traits\BlameableEntity;
use App\Traits\TimestampableEntity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
*
*/
class User implements UserInterface, \Serializable
{
use BlameableEntity;
use TimestampableEntity;
/**
* #var int
*
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string")
* #Assert\NotBlank()
*/
private $fullName;
/**
* #var string
*
* #ORM\Column(type="string", unique=true)
* #Assert\NotBlank()
* #Assert\Length(min=2, max=50)
*/
private $username;
/**
* #var string
*
* #ORM\Column(type="string", unique=true)
* #Assert\Email()
*/
private $email;
/**
* #var string
*
* #ORM\Column(type="string")
*/
private $password;
/**
* #var array
*
* #ORM\Column(type="json")
*/
private $roles = [];
/**
* #var \DateTime
*
* #ORM\Column(type="datetime", nullable=true)
*/
private $lastLogin;
/**
* #var \DateTime
*
* #ORM\Column(type="datetime", nullable=true)
*/
private $secondToLastLogin;
/**
* #ORM\ManyToOne(targetEntity="Service", inversedBy="users")
*/
private $service;
/**
* #ORM\ManyToMany(targetEntity="Child", mappedBy="users")
*/
private $children;
public function __construct()
{
$this->children = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getFullName(): ?string
{
return $this->fullName;
}
public function setFullName(string $fullName): self
{
$this->fullName = $fullName;
return $this;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returns the roles or permissions granted to the user for security.
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantees that a user always has at least one role for security
if (empty($roles)) {
$roles[] = 'ROLE_USER';
}
return array_unique($roles);
}
public function setRoles(array $roles): void
{
$this->roles = $roles;
}
/**
* Get the value of lastLogin
*
* #return \DateTime
*/
public function getLastLogin()
{
return $this->lastLogin;
}
/**
* Set the value of lastLogin
*
* #param \DateTime $lastLogin
*
* #return self
*/
public function setLastLogin(\DateTime $lastLogin)
{
$this->lastLogin = $lastLogin;
return $this;
}
/**
* Get the value of secondToLastLogin
*
* #return \DateTime
*/
public function getSecondToLastLogin()
{
return $this->secondToLastLogin;
}
/**
* Set the value of secondToLastLogin
*
* #param \DateTime $secondToLastLogin
*
* #return self
*/
public function setSecondToLastLogin(\DateTime $secondToLastLogin)
{
$this->secondToLastLogin = $secondToLastLogin;
return $this;
}
/**
*
* {#inheritdoc}
*/
public function getSalt(): ?string
{
return null;
}
/**
* Removes sensitive data from the user.
*
* {#inheritdoc}
*/
public function eraseCredentials(): void
{
// if you had a plainPassword property, you'd nullify it here
// $this->plainPassword = null;
}
/**
* {#inheritdoc}
*/
public function serialize(): string
{
// add $this->salt too if you don't use Bcrypt or Argon2i
return serialize([$this->id, $this->username, $this->password]);
}
/**
* {#inheritdoc}
*/
public function unserialize($serialized): void
{
// add $this->salt too if you don't use Bcrypt or Argon2i
[$this->id, $this->username, $this->password] = unserialize($serialized, ['allowed_classes' => false]);
}
/**
* Get the value of service
*/
public function getService()
{
return $this->service;
}
/**
* Set the value of service
*
* #return self
*/
public function setService($service)
{
$this->service = $service;
return $this;
}
public function hasService(): bool
{
return !empty($this->getService());
}
/**
* #return Collection|Child[]
*/
public function getChildren(): Collection
{
return $this->children;
}
public function addChild(Child $child): self
{
if (!$this->children->contains($child)) {
$this->children[] = $child;
$child->addUser($this);
}
return $this;
}
public function removeChild(Child $child): self
{
if ($this->children->removeElement($child)) {
$child->removeUser($this);
}
return $this;
}
public function __toString()
{
return $this->getFullName();
}
}
Service.php :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\ServiceRepository;
use App\Entity\Categorie;
use App\Entity\Departement;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* #ORM\Entity(repositoryClass=ServiceRepository::class)
*/
class Service
{
public const ASE = 'ASE';
public const MDPH = 'MDPH';
public const E_N = 'Éducation Nationale';
/**
* #var int
*
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string")
*/
private $nom;
/**
* #var Departement
*
* #ORM\ManyToOne(targetEntity="Departement")
* #ORM\JoinColumn(nullable=false)
*/
private $departement;
/**
* #var Categorie
*
* #ORM\ManyToOne(targetEntity="Categorie")
* #ORM\JoinColumn(nullable=false)
*/
private $categorie;
/**
* #ORM\OneToMany(targetEntity="User", mappedBy="service")
*/
private $users;
/**
* #ORM\ManyToMany(targetEntity="Child", mappedBy="services")
*/
private $children;
/**
* #ORM\ManyToMany(targetEntity="Element", mappedBy="services")
*/
private $elements;
public function __construct()
{
$this->users = new ArrayCollection();
$this->children = new ArrayCollection();
$this->elements = new ArrayCollection();
}
/**
* Get the value of id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set the value of id
*
* #param int $id
*
* #return self
*/
public function setId(int $id)
{
$this->id = $id;
return $this;
}
/**
* Get the value of nom
*
* #return string
*/
public function getNom()
{
return $this->nom;
}
/**
* Set the value of nom
*
* #param string $nom
*
* #return self
*/
public function setNom(string $nom)
{
$this->nom = $nom;
return $this;
}
/**
* Get the value of departement
*
* #return Departement
*/
public function getDepartement()
{
return $this->departement;
}
/**
* Set the value of departement
*
* #param Departement $departement
*
* #return self
*/
public function setDepartement(Departement $departement)
{
$this->departement = $departement;
return $this;
}
/**
* Get the value of categorie
*
* #return Categorie
*/
public function getCategorie()
{
return $this->categorie;
}
/**
* Set the value of categorie
*
* #param Categorie $categorie
*
* #return self
*/
public function setCategorie(Categorie $categorie)
{
$this->categorie = $categorie;
return $this;
}
/**
* #return Collection|Users[]
*/
public function getUsers(): Collection
{
return $this->users;
}
public function addUser(User $user): self
{
if (!$this->users->contains($user)) {
$this->users[] = $user;
$user->setService($this);
}
return $this;
}
public function removeUser(User $user): self
{
if ($this->users->removeElement($user)) {
// set the owning side to null (unless already changed)
if ($user->getService() === $this) {
$user->setService(null);
}
}
return $this;
}
/**
* #return Collection|Children[]
*/
public function getChildren(): Collection
{
return $this->children;
}
public function addChild(Child $child): self
{
if (!$this->children->contains($child)) {
$this->children[] = $child;
$child->addService($this);
}
return $this;
}
public function removeChild(Child $child): self
{
if ($this->children->removeElement($child)) {
$child->removeService($this);
}
return $this;
}
/**
* #return Collection|Elements[]
*/
public function getElements(): Collection
{
return $this->elements;
}
public function addElements(Element $element): self
{
if (!$this->children->contains($element)) {
$this->elements[] = $element;
$element->addService($this);
}
return $this;
}
public function removeElement(Element $element): self
{
if ($this->elements->removeElement($element)) {
$element->removeService($this);
}
return $this;
}
public function __toString()
{
return $this->getNom();
}
}
Child.php :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\Service;
use App\Entity\Sexe;
use App\Entity\User;
use DateTime;
use App\Repository\ChildRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use App\Traits\TimestampableEntity;
use App\Traits\BlameableEntity;
/**
* #ORM\Entity(repositoryClass=ChildRepository::class)
*/
class Child
{
use BlameableEntity;
use TimestampableEntity;
/**
* #var int
*
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string")
*/
private $nom;
/**
* #var string
*
* #ORM\Column(type="string")
*/
private $prenom;
/**
* #var Sexe
*
* #ORM\ManyToOne(targetEntity="Sexe")
*/
private $sexe;
/**
* #var date
*
* #ORM\Column(type="date")
*/
private $dateDeNaissance;
/**
* #var string
*
* #ORM\Column(type="string")
*/
private $lieuDeNaissance;
/**
* #var string
*
* #ORM\Column(type="string")
*/
private $nationalite;
/**
* #var date
*
* #ORM\Column(type="datetime", nullable=true)
*/
private $dateElaborationPpe;
/**
* #var Service[]|Collection
*
* #ORM\ManyToMany(targetEntity="Service", inversedBy="children")
*/
private $services;
/**
* #var User[]|Collection
*
* #ORM\ManyToMany(targetEntity="User", inversedBy="children")
*/
private $users;
/**
* #var Element[]|Collection
*
* #ORM\OneToMany(targetEntity="Element", mappedBy="child")
*/
private $elements;
public function __construct()
{
$this->services = new ArrayCollection();
$this->users = new ArrayCollection();
$this->elements = new ArrayCollection();
}
/**
* Get the value of id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set the value of id
*
* #param int $id
*
* #return self
*/
public function setId(int $id)
{
$this->id = $id;
return $this;
}
/**
* Get id
*
* #return string
*/
public function getNumDossier()
{
return str_pad($this->id, 6, "0", STR_PAD_LEFT);
}
/**
* Get the value of nom
*/
public function getNom()
{
return $this->nom;
}
/**
* Set the value of nom
*
* #return self
*/
public function setNom(string $nom)
{
$this->nom = $nom;
return $this;
}
/**
* Get the value of prenom
*/
public function getPrenom()
{
return $this->prenom;
}
/**
* Set the value of prenom
*
* #return self
*/
public function setPrenom(string $prenom)
{
$this->prenom = $prenom;
return $this;
}
/**
* Get the value of sexe
*
* #return Sexe
*/
public function getSexe()
{
return $this->sexe;
}
/**
* Set the value of sexe
*
* #param Sexe $sexe
*
* #return self
*/
public function setSexe(Sexe $sexe)
{
$this->sexe = $sexe;
return $this;
}
/**
* Get the value of dateDeNaissance
*/
public function getDateDeNaissance()
{
return $this->dateDeNaissance;
}
/**
* Set the value of dateDeNaissance
*
* #return self
*/
public function setDateDeNaissance(datetime $dateDeNaissance)
{
$this->dateDeNaissance = $dateDeNaissance;
return $this;
}
/**
* Get the value of lieuDeNaissance
*/
public function getLieuDeNaissance()
{
return $this->lieuDeNaissance;
}
/**
* Set the value of lieuDeNaissance
*
* #return self
*/
public function setLieuDeNaissance(string $lieuDeNaissance)
{
$this->lieuDeNaissance = $lieuDeNaissance;
return $this;
}
/**
* Get the value of nationalite
*/
public function getNationalite()
{
return $this->nationalite;
}
/**
* Set the value of nationalite
*
* #return self
*/
public function setNationalite(string $nationalite)
{
$this->nationalite = $nationalite;
return $this;
}
/**
* Get the value of dateElaborationPpe
*/
public function getDateElaborationPpe()
{
return $this->dateElaborationPpe;
}
/**
* Set the value of dateElaborationPpe
*
* #return self
*/
public function setDateElaborationPpe(datetime $dateElaborationPpe)
{
$this->dateElaborationPpe = $dateElaborationPpe;
return $this;
}
/**
* #return Collection|Service[]
*/
public function getServices(): Collection
{
return $this->services;
}
public function addService(Service $service): self
{
if (!$this->services->contains($service)) {
$this->services[] = $service;
}
return $this;
}
public function removeService(Service $service): self
{
$this->services->removeElement($service);
return $this;
}
/**
* #return Collection|User[]
*/
public function getUsers(): Collection
{
return $this->users;
}
public function addUser(User $user): self
{
$test = 'test';
if (!$this->users->contains($user)) {
$this->users[] = $user;
}
return $this;
}
public function removeUser(User $user): self
{
$this->users->removeElement($user);
return $this;
}
public function getNbUsers()
{
return count($this->getUsers());
}
/**
* #return Collection|Element[]
*/
public function getElements(): Collection
{
return $this->elements;
}
public function addElement(Element $element): self
{
if (!$this->elements->contains($element)) {
$this->elements[] = $element;
}
return $this;
}
public function removeElement(Element $element): self
{
$this->elements->removeElement($element);
return $this;
}
public function isNotAssigned(): bool
{
return (!$this->getNbUsers());
}
public function __toString(): string
{
return $this->getNom() . ' ' . $this->getPrenom();
}
}
Thanks in advance for your help.

Symfony 4 Add ManyToMany Entity trough FORM

I am heavily stuck on problem with inserting data trough html.twig when passing one Entity to the other. I am able to add or edit single entities but i cant figure out how to handle adding relations.
Tournament Entity class - unimportant stuff deleted
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* Tournament.
*
* #ORM\Table(name="tournament")
* #ORM\Entity(repositoryClass="App\Repository\TournamentRepository")
*/
class Tournament
{
/**
* #var int
*
* #ORM\Column(name="id_tournament", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idTournament;
/**
* #var string
*
* #ORM\Column(name="name_of_event", type="string", length=128, nullable=false)
*/
private $nameOfEvent;
/**
* #var string
*
* #ORM\Column(name="type", type="string", length=16, nullable=false)
*/
private $type;
/**
* #var string
*
* #ORM\Column(name="prizepool", type="string", length=32, nullable=false)
*/
private $prizepool;
/**
* #var string
*
* #ORM\Column(name="location", type="string", length=128, nullable=false)
*/
private $location;
/**
* #var string
*
* #ORM\Column(name="country", type="string", length=32, nullable=false)
*/
private $country;
/**
* #var \DateTime
*
* #ORM\Column(name="start_date", type="date", nullable=false)
*/
private $startDate;
/**
* #var \DateTime
*
* #ORM\Column(name="end_date", type="date", nullable=false)
*/
private $endDate;
/**
* #var string|null
*
* #ORM\Column(name="tournament_Img", type="string", length=64, nullable=true, options={"default"="NULL"})
*/
private $tournamentImg = 'NULL';
/**
* #ORM\OneToMany(targetEntity="App\Entity\Eventstandings", mappedBy="tourn")
*/
private $events;
/**
* #ORM\OneToMany(targetEntity=Comment::class, mappedBy="tourn_id")
*/
private $comments;
/**
* #ORM\ManyToMany(targetEntity=Team::class, inversedBy="tournaments")
* #ORM\JoinTable(name="playedAt", joinColumns={#ORM\JoinColumn(name="tourn_id", referencedColumnName="id_tournament")},
* inverseJoinColumns={#ORM\JoinColumn(name="team_id", referencedColumnName="ID_Team")})
*/
private $teams;
/**
* #return ArrayCollection
*/
public function getEvents(): Collection
{
return $this->events;
}
/**
* #param ArrayCollection $events
*/
public function setEvents(Collection $events): void
{
$this->events = $events;
}
public function __construct()
{
$this->teams = new ArrayCollection();
$this->events = new ArrayCollection();
$this->comments = new ArrayCollection();
}
public function getIdTournament(): ?int
{
return $this->idTournament;
}
public function addTeam(Team $team): self
{
if (!$this->teams->contains($team)) {
$this->teams[] = $team;
}
return $this;
}
public function removeTeam(Team $team): self
{
if ($this->teams->contains($team)) {
$this->teams->removeElement($team);
}
return $this;
}
}
Team Entity class
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\PersistentCollection;
/**
* Team.
*
* #ORM\Table(name="team")
* #ORM\Entity(repositoryClass="App\Repository\TeamRepository")
*/
class Team
{
/**
* #var int
*
* #ORM\Column(name="ID_Team", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idTeam;
/**
* #var string
*
* #ORM\Column(name="Name", type="string", length=128, nullable=false)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="Region", type="text", length=65535, nullable=false)
*/
private $region;
/**
* #var string
*
* #ORM\Column(name="Coach", type="string", length=64, nullable=false)
*/
private $coach;
/**
* #var string
*
* #ORM\Column(name="Total_Earnings", type="string", length=64, nullable=false)
*/
private $totalEarnings;
/**
* #var string|null
*
* #ORM\Column(name="img_Path", type="string", length=64, nullable=true, options={"default"="NULL"})
*/
private $imgPath = 'NULL';
/**
* #ORM\OneToMany(targetEntity=Player::class, mappedBy="team", cascade={"persist","remove"})
*/
private $ownedPlayers;
/**
* #var string|null
*
* #ORM\Column(name="player_Img", type="string", length=64, nullable=true, options={"default"="NULL"})
*/
private $playerImg = 'NULL';
/**
* #ORM\OneToMany(targetEntity="App\Entity\Eventstandings", mappedBy="team")
*/
private $playedEventAsoc;
/**
* #ORM\ManyToMany(targetEntity=Tournament::class, mappedBy="teams")
*/
private $tournaments;
public function getIdTeam(): ?int
{
return $this->idTeam;
}
public function __construct()
{
$this->tournaments = new ArrayCollection();
$this->playedEventAsoc = new ArrayCollection();
$this->ownedPlayers = new ArrayCollection();
}
public function getPlayedEventAsoc(): Collection
{
return $this->playedEventAsoc;
}
public function setPlayedEventAsoc(Collection $playedEventAsoc): void
{
$this->playedEventAsoc = $playedEventAsoc;
}
public function getStandings(): void
{
$standings = getPlayedEventAsoc().$this->getStandings();
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getRegion(): ?string
{
return $this->region;
}
public function setRegion(string $region): self
{
$this->region = $region;
return $this;
}
public function getCoach(): ?string
{
return $this->coach;
}
public function setCoach(string $coach): self
{
$this->coach = $coach;
return $this;
}
public function getTotalEarnings(): ?string
{
return $this->totalEarnings;
}
public function setTotalEarnings(string $totalEarnings): self
{
$this->totalEarnings = $totalEarnings;
return $this;
}
public function getImgPath(): ?string
{
return $this->imgPath;
}
public function setImgPath(?string $imgPath): self
{
$this->imgPath = $imgPath;
return $this;
}
public function getPlayerImg(): ?string
{
return $this->playerImg;
}
public function setPlayerImg(?string $playerImg): self
{
$this->playerImg = $playerImg;
return $this;
}
public function addPlayer(Player $player): self
{
if (!$this->ownedPlayers->contains($player)) {
$this->ownedPlayers[] = $player;
$player->setTeam($this);
}
return $this;
}
public function removePlayer(Player $player): self
{
if ($this->ownedPlayers->contains($player)) {
$this->ownedPlayers->removeElement($player);
// set the owning side to null (unless already changed)
if ($player->getTeam() === $this) {
$player->setTeam(null);
}
}
return $this;
}
/**
* #return Collection|Player[]
*/
public function getOwnedPlayers(): Collection
{
return $this->ownedPlayers;
}
public function addOwnedPlayer(Player $ownedPlayer): self
{
if (!$this->ownedPlayers->contains($ownedPlayer)) {
$this->ownedPlayers[] = $ownedPlayer;
$ownedPlayer->setTeam($this);
}
return $this;
}
public function removeOwnedPlayer(Player $ownedPlayer): self
{
if ($this->ownedPlayers->contains($ownedPlayer)) {
$this->ownedPlayers->removeElement($ownedPlayer);
// set the owning side to null (unless already changed)
if ($ownedPlayer->getTeam() === $this) {
$ownedPlayer->setTeam(null);
}
}
return $this;
}
public function addEvents(Eventstandings $event): self
{
if (!$this->playedEventAsoc->contains($event)) {
$this->playedEventAsoc[] = $event;
$event->setTeam($this);
}
return $this;
}
public function removeEvents(Eventstandings $event): self
{
if ($this->playedEventAsoc->contains($event)) {
$this->playedEventAsoc->removeElement($event);
// set the owning side to null (unless already changed)
if ($event->getTeam() === $this) {
$event->setTeam(null);
}
}
return $this;
}
public function addEvent(Eventstandings $event): self
{
if (!$this->playedEventAsoc->contains($event)) {
$this->playedEventAsoc[] = $event;
$event->setTeam($this);
}
return $this;
}
public function removeEvent(Eventstandings $event): self
{
if ($this->playedEventAsoc->contains($event)) {
$this->playedEventAsoc->removeElement($event);
// set the owning side to null (unless already changed)
if ($event->getTeam() === $this) {
$event->setTeam(null);
}
}
return $this;
}
public function getEventData(PersistentCollection $playedEvents): array
{
$eventdata = $playedEvents->getValues();
return $eventdata;
}
public function addPlayedEventAsoc(Eventstandings $playedEventAsoc): self
{
if (!$this->playedEventAsoc->contains($playedEventAsoc)) {
$this->playedEventAsoc[] = $playedEventAsoc;
$playedEventAsoc->setTeam($this);
}
return $this;
}
public function removePlayedEventAsoc(Eventstandings $playedEventAsoc): self
{
if ($this->playedEventAsoc->contains($playedEventAsoc)) {
$this->playedEventAsoc->removeElement($playedEventAsoc);
// set the owning side to null (unless already changed)
if ($playedEventAsoc->getTeam() === $this) {
$playedEventAsoc->setTeam(null);
}
}
return $this;
}
/**
* #return Collection|Tournament[]
*/
public function getTournaments(): Collection
{
return $this->tournaments;
}
public function addTournament(Tournament $tournament): self
{
if (!$this->tournaments->contains($tournament)) {
$this->tournaments[] = $tournament;
$tournament->addTeam($this);
}
return $this;
}
public function removeTournament(Tournament $tournament): self
{
if ($this->tournaments->contains($tournament)) {
$this->tournaments->removeElement($tournament);
$tournament->removeTeam($this);
}
return $this;
}
}
I am able to edit tournament or team data trough forms and save it to database.
What I am not able is to add data into this relation.
Form Class for this
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('team', EntityType::class, array(
'class' => Team::class,
'multiple' => true,
'expanded' => true,
))
->add('Add Team', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Tournament::class
]);
}
Tournament Controller method addTeam - should add Team Entity into Trounament teams collection
/**
* #param Team $team
* #param Request $request
* #Route("/addTeamToEvent/{idTournament}",name="addTeamToEvent")
* #return RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function addTeam(Tournament $tournament, Request $request)
{
$form = $this->createForm(TeamToEvent::class, $tournament);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($tournament);
$this->entityManager->flush();
return new RedirectResponse($this->router->generate('welcome'));
}
return $this->render('welcome/addTeamToEvent.html.twig', ['form' => $form->createView()]);
}
What should be the right aproach? I am totaly lost and i don't know how to do this.

getRole() form RoleInterface returns empty on symfony

i have a big problem implementing JWT Tokens on symfony.
I already make work the JWT token, but i need to add to the token info the User roles too. i am doing this using a Listener (JWTCreatedListener):
public function onJWTCreated(JWTCreatedEvent $event)
{
$request = $this->requestStack->getCurrentRequest();
$payload = $event->getData();
$payload['ip'] = $request->getClientIp();
$payload['roles'] = $event->getUser()->getRoles();
$event->setData($payload);
}
I implemented the Role.php (AppBundle/Entity/Role.php) on this way:
<?php
namespace AppBundle\Entity;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="acme_role")
* #ORM\Entity()
*/
class Role implements RoleInterface
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=30)
*/
private $name;
/**
* #ORM\Column(name="role", type="string", length=20, unique=true)
*/
private $role;
/**
* #ORM\ManyToMany(targetEntity="User", mappedBy="roles")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
/**
* #see RoleInterface
*/
public function getRole()
{
return $this->role;
}
// ... getters and setters for each property
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Role
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set role
*
* #param string $role
*
* #return Role
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Add user
*
* #param \AppBundle\Entity\User $user
*
* #return Role
*/
public function addUser(\AppBundle\Entity\User $user)
{
$this->users[] = $user;
return $this;
}
/**
* Remove user
*
* #param \AppBundle\Entity\User $user
*/
public function removeUser(\AppBundle\Entity\User $user)
{
$this->users->removeElement($user);
}
/**
* Get users
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
}
And my User class:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Table(name="users")
* #ORM\Entity
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\Column(type="string", length=500)
*/
private $password;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="users")
*
*/
private $roles;
public function __construct($username)
{
$this->isActive = true;
$this->username = $username;
$this->roles = new ArrayCollection();
}
public function getUsername()
{
return $this->username;
}
public function getSalt()
{
return null;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
}
public function getRoles()
{
return $this->roles->toArray();
}
public function eraseCredentials()
{
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
*
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set isActive
*
* #param boolean $isActive
*
* #return User
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* Add role
*
* #param \AppBundle\Entity\Role $role
*
* #return User
*/
public function addRole(\AppBundle\Entity\Role $role)
{
$this->roles[] = $role;
return $this;
}
/**
* Remove role
*
* #param \AppBundle\Entity\Role $role
*/
public function removeRole(\AppBundle\Entity\Role $role)
{
$this->roles->removeElement($role);
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
// serialize and unserialize must be updated - see below
public function serialize()
{
return serialize(array(
// ...
$this->isActive
));
}
public function unserialize($serialized)
{
list (
// ...
$this->isActive
) = unserialize($serialized);
}
}
The problem is that this method getRole() always returns empty.
This is my db data:
[users]
id username password is_active
1 abriceno $2y$13$NW6uNOKJGUQTSXirej4HKOwIa6mWzYqFxzz1ppWQjyp... 1
[acme_role]
id name role
1 admin ROLE_ADMIN
[user_role]
user_id user_role
1 1
Also, i try to call the data from a controller test using doctrine:
public function indexAction(Request $request)
{
$repository = $this->getDoctrine()->getRepository('AppBundle:User');
$user = $repository->findOneByusername('abriceno');
$username = $user->getUsername();
$roles = $user->getRoles();
$arr = array(
'username' => $user->getUsername(),
'password' => $user->getPassword(),
'roles' => $user->getRoles()
);
return new JsonResponse($arr);
this returns:
{"username":"abriceno","password":"$2y$13$NW6uNOKJGUQTSXirej4HKOwIa6mWzYqFxzz1ppWQjypQJLIgUGJ.m","roles":[{}]}
I am so desperate... thanks for all the help that you can provide to me.
UPDATE 1
If i do print_r($role) this prints a huuuuuge list of values:
array(1) { [0]=> object(AppBundle\Entity\Role)#624 (4) { ["id":"AppBundle\Entity\Role":private]=> int(1) ["name":"AppBundle\Entity\Role":private]=> string(5) "admin" ["role":"AppBundle\Entity\Role":private]=> string(10) "ROLE_ADMIN" ["users":"AppBundle\Entity\Role":private]=> object(Doctrine\ORM\PersistentCollection)#626 (9) { ["snapshot":"Doctrine\ORM\PersistentCollection":private]=> array(0) { } ["owner":"Doctrine\ORM\PersistentCollection":private]=> *RECURSION*
... and keeps going... very strange!!
Seems that the join table is not handled directly by doctrine, so you need do specify to doctrine howto map the referenced fied with the JoinTable annotation (See the default mapping section.)
In your case, try to modify the roles relation definition in the User entity as follow:
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="users")
* #ORM\JoinTable(name="user_role",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_role", referencedColumnName="id")})
*
*/
private $roles;
Hope this help
Finally i fix this with this code:
// Work of roles
$roles = $event->getUser()->getRoles();
$role_length = count($roles);
$role_list = array();
for ($i=0; $i <$role_length ; $i++) {
array_push($role_list,$roles[$i]->getRole());
}
$payload = $event->getData();
$payload['ip'] = $request->getClientIp();
$payload['roles'] = $role_list;
The problem (i guess) is on the ->getRoles(); code. This returns a array of Entity\Role class, not an array of roles.
Now the dump is:
{
"token": "eyJhbGciOiJSUzI1NiJ9.....",
"data": {
"roles": [
"ROLE_ADMIN"
]
}
}

Adding many to many relationship into database Symfony

I'm trying to add new user with ManyToMany relationship with group, but only user is saving in database
this is my
User.php
/**
* Acme\UserBundle\Entity\User
*
* #ORM\Table(name="User")
* #ORM\Entity(repositoryClass="Acme\UserBundle\Entity\UserRepository")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="username", type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\Column(name="salt", type="string", length=40)
*/
private $salt;
/**
* #ORM\Column(name="password", type="string", length=40)
*/
private $password;
/**
* #ORM\Column(name="email", type="string", length=60, unique=true)
*/
private $email;
/**
* #ORM\Column(name="isActive", type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToMany(targetEntity="Group", inversedBy="users")
*
* #ORM\JoinTable(name="user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*
*/
private $groups;
public function __construct()
{
$this->isActive = true;
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
$this->groups = new ArrayCollection();
}
/**
* #inheritDoc
*/
public function getRoles()
{
$roles = array();
foreach ($this->groups as $role) {
$roles[] = $role->getRole();
}
return $roles;
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
/*
* ! Don't serialize $roles field !
*/
return \json_encode(array(
$this->id,
$this->username,
$this->email,
$this->salt,
$this->password,
$this->isActive
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->email,
$this->salt,
$this->password,
$this->isActive
) = \json_decode($serialized);
}
public function eraseCredentials()
{
}
public function getUsername()
{
return $this->username;
}
public function getSalt()
{
return $this->salt;
}
public function getPassword()
{
return $this->password;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set salt
*
* #param string $salt
* #return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set isActive
*
* #param boolean $isActive
* #return User
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* Add groups
*
* #param \Acme\UserBundle\Entity\Group $groups
* #return User
*/
public function addGroup(\Acme\UserBundle\Entity\Group $groups)
{
$groups->addUser($this);
$this->groups -> add($groups);
return $this->groups;
}
/**
* Remove groups
*
* #param \Acme\UserBundle\Entity\Group $groups
*/
public function removeGroup(\Acme\UserBundle\Entity\Group $groups)
{
$this->groups->removeElement($groups);
}
/**
* Get groups
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGroups()
{
return $this->groups;
}
}
my Group.php
<?php
namespace Acme\UserBundle\Entity;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="groups")
* #ORM\Entity
*/
class Group implements RoleInterface, \Serializable
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/** #ORM\Column(name="name", type="string", length=30) */
private $name;
/** #ORM\Column(name="role", type="string", length=20, unique=true) */
private $role;
/** #ORM\ManyToMany(targetEntity="User", mappedBy="groups",cascade={"persist"}) */
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
// ... getters and setters for each property
/** #see RoleInterface */
public function getRole()
{
return $this->role;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
/*
* ! Don't serialize $users field !
*/
return \json_encode(array(
$this->id,
$this->role
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list(
$this->id,
$this->role
) = \json_decode($serialized);
}
/**
* Set name
*
* #param string $name
* #return Group
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set role
*
* #param string $role
* #return Group
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Add users
*
* #param \Acme\UserBundle\Entity\User $users
* #return Group
*/
public function addUser(\Acme\UserBundle\Entity\User $users)
{
$this->users[] = $users;
return $this;
}
/**
* Remove users
*
* #param \Acme\UserBundle\Entity\User $users
*/
public function removeUser(\Acme\UserBundle\Entity\User $users)
{
$this->users->removeElement($users);
}
/**
* Get users
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
}
and fragment from my controller
public function newAction(Request $request)
{
$user = new User();
$form = $this->createFormBuilder($user)
->add('username', 'text')
->add('password', 'text')
->add('email', 'email')
->add('submit','submit')
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$user=$form->getData();
$group=new Group();
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$user->setSalt(md5(time()));
$pass = $encoder->encodePassword($form->getData()->getPassword(), $user->getSalt());
$user->setPassword($pass);
$group->setRole('ROLE_USER');
$user->addGroup($group);
$em = $this->getDoctrine()->getManager();
$em->merge($user);
$em->flush();
return $this->redirect($this->generateUrl('login'));
}
return $this->render('AcmeUserBundle:User:new.html.twig', array(
'form' => $form->createView(),
));
in database i have 3 table : User, Group and user_group (user_id, group_id)
everything generated from entities. I can register new user but it isnt saving in user_group.
Thanks for any help.
Ps.Sorry for my poor english
From what i can tell, you're not saving your group. So because you're not saving it, there is no user_group to save, because your group doesn't exist in the database. However you'll have another problem once you do this because you have a unique constraint on the role field for your group, so you'll get a database error saying you have a duplicate once you try to register more than one person. You'll need to pull the group from the db instead of making a new one every time.
$group = $this->em->getRepository('Group')->findOneByRole('ROLE_USER');
$user->addGroup($group);
$em->persist($group);
$em->persist($user);
$em->flush();
Update your controller to contain:
$group = $em->getRepository('AcmeUserBundle:Group')->findOne(array('role' => 'ROLE_USER'));
$user->addGroup($group);
$em->persist($user);
$em->persist($group);
$em->flush();
You forgot to persist the Group entity in your code, so it didn't save any data.
By the way, I suggest using a UserService that handles all that logic instead of putting it all in your controllers.
Also, in your User.php, you can just do:
/**
* #ORM\ManyToMany(targetEntity="Group", inversedBy="user")
*/
protected $groups;
The #JoinColumn annotation is not required. If it is not specified the attributes name and referencedColumnName are inferred from the table and primary key names.

Symfony 2 Must Implement UserProviderInterface

I get this error 'Must implement UserProviderInterface'
when trying to using the symfony login features. I'm referencing the repository * #ORM\Entity(repositoryClass="Login\LogBundle\Entity\Repository\UserRepository") . Does anyone have any ideas.
Entity
<?php
namespace Login\LogBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
/**
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="Login\LogBundle\Entity\Repository\UserRepository")
* #ORM\HasLifecycleCallbacks()
*/
class User implements UserInterface, \Serializable
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $password;
/**
* #var string
*/
private $name;
/**
* #var string
*/
private $username;
/**
* #ORM\Column(type="string", length=32)
*/
private $salt;
/**
* #ORM\Column(type="string", length=60, unique=true)
*/
private $email;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
/**
* #OneToMany(targetEntity="userapidetails", mappedBy="user")
*/
public $userapidetails;
public function __construct()
{
$this->userapidetails = new ArrayCollection();
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}
public function getUserapidetails() {
return $this->userapidetails;
}
// public function setUserapidetails($userapidetails) {
// $this->userapi=$userapidetails;
// return $this;
// }
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set name
*
* #param string $name
* #return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* #var string
*/
private $isactive;
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set salt
*
* #param string $salt
* #return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Get salt
*
* #return string
*/
public function getSalt()
{
return $this->salt;
}
/**
* Set isactive
*
* #param string $isactive
* #return User
*/
public function setIsactive($isactive)
{
$this->isactive = $isactive;
return $this;
}
/**
* Get isactive
*
* #return string
*/
public function getIsactive()
{
return $this->isactive;
}
/**
* #inheritDoc
*/
public function getRoles()
{
return array('ROLE_USER');
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->salt,
$this->password,
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->salt,
$this->password,
) = unserialize($serialized);
}
}
Repository
// src/Acme/UserBundle/Entity/UserRepository.php
namespace Login\LogBundle\Entity;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\ORM\NoResultException;
class UserRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$q = $this
->createQueryBuilder('u')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery();
try {
// The Query::getSingleResult() method throws an exception
// if there is no record matching the criteria.
$user = $q->getSingleResult();
} catch (NoResultException $e) {
$message = sprintf(
'Unable to find an active admin AcmeUserBundle:User object identified by "%s".',
$username
);
throw new UsernameNotFoundException($message, 0, $e);
}
return $user;
}
public function refreshUser(UserInterface $user)
{
$class = get_class($user);
if (!$this->supportsClass($class)) {
throw new UnsupportedUserException(
sprintf(
'Instances of "%s" are not supported.',
$class
)
);
}
return $this->find($user->getId());
}
public function supportsClass($class)
{
return $this->getEntityName() === $class
|| is_subclass_of($class, $this->getEntityName());
}
}
Check the app/config/security.yml file with something like this:
# app/config/security.yml
security:
providers:
main:
entity:
class: Acme\UserBundle\Entity\User
property: username
And path to repositoryClass UserRepository is wrong, maybe you mean this:
#ORM\Entity(repositoryClass="Login\LogBundle\Entity\UserRepository")
becouse you use namespace \Login\LogBundle\Entity\UserRepository.
To load user from Repository, you should omit the { property: username } from security.yml.

Categories