I have 2 entities, Parking and Agent, each parking can have many Agents and each Agent can administer many parkings.
After I created the relationship, Doctrine automatically added a join table called parking-Agent.
Now I'm trying to populate that table through a form, like when creating a new Agent I can give him one or many parkings, or Vice-Versa. I tried adding a choicetype with multiple choices to the form but it didn't work.
Can you guys help me ?
Entity Agent:
<?php
/**
* #ORM\Entity
* #UniqueEntity(fields="username", message="Username already taken")
*/
class Agent implements UserInterface
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
public function getId()
{
return $this->id;
}
/**
* #ORM\Column(type="string", length=191, unique=true)
* #Assert\NotBlank()
*/
private $username;
/**
* #Assert\Length(max=191)
*/
private $plainPassword;
/**
* The below length depends on the "algorithm" you use for encoding
* the password, but this works well with bcrypt.
*
* #ORM\Column(type="string", length=64)
*/
private $password;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Parking", mappedBy="agents")
*/
private $parkings;
public function __construct()
{
$this->parkings = new ArrayCollection();
}
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
}
public function getPlainPassword()
{
return $this->plainPassword;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
$this->password = null;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
if (!is_null($password)) {
$this->password = $password;
}
return $this;
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
/**
* #return Collection|Parking[]
*/
public function getParkings(): Collection
{
return $this->parkings;
}
public function addParking(Parking $parking): self
{
if (!$this->parkings->contains($parking)) {
$this->parkings[] = $parking;
$parking->addAgent($this);
return $this;
}
return $this;
}
public function removeParking(Parking $parking): self
{
if ($this->parkings->contains($parking)) {
$this->parkings->removeElement($parking);
$parking->removeAgent($this);
}
return $this;
}
}
Entity Parking:
<?php
/**
* #ORM\Entity(repositoryClass="App\Repository\ParkingRepository")
*/
class Parking
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=55)
*/
private $libelle;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\agent", inversedBy="parkings")
*/
private $agents;
public function __construct()
{
$this->agents = new ArrayCollection();
$this->voitures = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getLibelle(): ?string
{
return $this->libelle;
}
public function setLibelle(string $libelle): self
{
$this->libelle = $libelle;
return $this;
}
/**
* #return Collection|agent[]
*/
public function getAgents(): Collection
{
return $this->agents;
}
public function addAgent(Agent $agent): self
{
if (!$this->agents->contains($agent)) {
$this->agents[] = $agent;
}
return $this;
}
public function removeAgent(Agent $agent): self
{
if ($this->agents->contains($agent)) {
$this->agents->removeElement($agent);
}
return $this;
}
}
My Form:
<?php
namespace App\Form;
ass ParkingType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('libelle');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Parking::class,
]);
}
}
You can try it with a field where you can select multiple elements. The Select2:
->add('personsconcerned', ChoiceType::class, [
'label' => 'form.personsconcerned',
'choices' => $this->groupService->getMailGroups(),
'multiple' => 'multiple',
'mapped' => false,
'choice_translation_domain' => false,
'attr' => [
'data-select' => 'true'
],
'data' => $mailgroups
])
In this example you can see an Element with the posibillity to select more than one thing.
The important thing is the attribute 'multiple', set this to 'multiple' or true.
Related
The flush function does not add anything to the database even though it doesn't return any error.
Any idea of how can I solve that?
Thanks in advance for your help!
Here is my code:
Controller:
#[Route("/messages")]
public function create(Request $request, ManagerRegistry $signup, UserRepository $userRepository, MessageRepository $messageRepository): Response
{
$message = new Message();
$userRepository = $signup->getRepository(User::class);
$formdico = [];
foreach ($userRepository->findAll() as $user) {
$userform = $this->createForm(MessageType::class, $message);
$formdico[$user->getId()] = $userform;
}
foreach ($formdico as $form) {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$newMessage = new Message();
$newMessage->setSender($userRepository->findOneById($form->getData()->getSender()));
$newMessage->setReceiver($userRepository->findOneById($form->getData()->getSender()));
$newMessage->setContent($form->getData()->getContent());
$newMessage->setCreatedAt(new \DateTime('now'));
$em = $signup->getManager();
$em->persist($newMessage);
$em->flush($newMessage);
}
}
foreach ($userRepository->findAll() as $user) {
$userform = $this->createForm(MessageType::class, $message);
$formdico[$user->getId()] = $userform->createView();
}
return $this->render('message/readAllUser.html.twig', ['users' => $userRepository->findAll(), "formdico" => $formdico, 'messages' => $messageRepository->findAll()]);
}
Entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity()]
class Message
{
#[ORM\Id]
#[ORM\GeneratedValue(strategy: "AUTO")]
#[ORM\Column(type: "integer")]
private int $id;
#[ORM\ManyToOne(targetEntity: "App\Entity\User", inversedBy: "sendedMessages")]
private $sender;
#[ORM\ManyToOne(targetEntity: "App\Entity\User", inversedBy: "receivedMessages")]
private $receiver;
#[ORM\Column(type: "text")]
private string $content;
#[ORM\Column(type: "date")]
private \DateTime $createdAt;
/**
* Get the value of id
*/
public function getId()
{
return $this->id;
}
/**
* Set the value of id
*
* #return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get the value of sender
*/
public function getSender()
{
return $this->sender;
}
/**
* Set the value of sender
*
* #return self
*/
public function setSender($sender)
{
$this->sender = $sender;
return $this;
}
/**
* Get the value of receiver
*/
public function getReceiver()
{
return $this->receiver;
}
/**
* Set the value of receiver
*
* #return self
*/
public function setReceiver($receiver)
{
$this->receiver = $receiver;
return $this;
}
/**
* Get the value of content
*/
public function getContent()
{
return $this->content;
}
/**
* Set the value of content
*
* #return self
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get the value of createdAt
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set the value of createdAt
*
* #return self
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
}
Form:
<?php
namespace App\Form;
use App\Entity\Message;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
class MessageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('sender', IntegerType::class, [])
->add('content', TextType::class, ['label' => false, 'attr' => ['placeholder' => 'Message Content']])
->add('receiver', IntegerType::class, []);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(['data_class' => Message::class,]);
}
}
I tried removing the persist, dumped a lot of things to try understanding the problem but I can't get to solve this...
And the form is valid
I'm fairly new to the Symfony universe, so please bear with me if this question has already been answered.
I have provided endpoints with the api-platform to create a RegistrationRequest. A RegistrationRequest has a user that is connected via a ManyToOne relation, so it is stored in another table. In the API, the user or user_id is read-only, this is why the user can not be set in the post data. If a RegistrationRequest is made via the API, the creation fails because the user_id is obviously null.
This is why I would like to set the user manually after a registration request is made via the API but before the RegistrationRequest is stored in the database.
The user is known via the global REMOTE_USER from where I can derive the corresponding user object.
src/Entity/RegistrationRequest.php:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=App\Repository\RegistrationRequestRepository::class)
* #ApiResource(
* normalizationContext={"groups" = {"read"}},
* denormalizationContext={"groups" = {"write"}},
* paginationEnabled=false,
* )
*/
class RegistrationRequest
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #Groups({"read"})
*/
private $id;
/**
* #ORM\Column(type="string", length=64, nullable=true)
* #Groups({"read", "write"})
*/
private $opt_email;
/**
* #ORM\Column(type="string", length=255, nullable=true)
* #Groups({"read", "write"})
*/
private $title;
/**
* #Gedmo\Mapping\Annotation\Timestampable(on="create")
* #ORM\Column(type="datetime")
* #Groups({"read"})
*/
private $created_at;
/**
* #Gedmo\Mapping\Annotation\Timestampable(on="update")
* #ORM\Column(type="datetime")
* #Groups({"read"})
*/
private $updated_at;
/**
* #ORM\Column(type="text", nullable=true)
* #Groups({"read", "write"})
*/
private $notes;
/**
* #ORM\Column(type="string", length=16)
* #Groups({"read", "write"})
*/
private $language_code;
/**
* #ORM\Column(type="text")
* #Groups({"read", "write"})
*/
private $data;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="registrationRequests")
* #ORM\JoinColumn(nullable=false)
*/
private $user;
public function getId(): ?int
{
return $this->id;
}
public function getOptEmail(): ?string
{
return $this->opt_email;
}
public function setOptEmail(?string $opt_email): self
{
$this->opt_email = $opt_email;
return $this;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(?string $title): self
{
$this->title = $title;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->created_at;
}
public function setCreatedAt(\DateTimeInterface $created_at): self
{
$this->created_at = $created_at;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updated_at;
}
public function setUpdatedAt(\DateTimeInterface $updated_at): self
{
$this->updated_at = $updated_at;
return $this;
}
public function getNotes(): ?string
{
return $this->notes;
}
public function setNotes(?string $notes): self
{
$this->notes = $notes;
return $this;
}
public function getLanguageCode(): ?string
{
return $this->language_code;
}
public function setLanguageCode(string $language_code): self
{
$this->language_code = $language_code;
return $this;
}
public function getData(): ?string
{
return $this->data;
}
public function setData(string $data): self
{
$this->data = $data;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
}
src/Controller/RegistrationRequestController.php:
<?php
namespace App\Controller;
use App\Service\IGSNService;
use App\Entity\RegistrationRequest;
use App\Form\RegistrationRequestType;
use App\Repository\RegistrationRequestRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* #Route("/registration_request")
*/
class RegistrationRequestController extends AbstractController
{
/**
* #Route("/")
*/
public function indexNoLocale(): Response
{
return $this->redirectToRoute('app_registration_request_index', ['_locale' => 'de']);
}
/**
* #Route("/{_locale<%app.supported_locales%>}/", name="app_registration_request_index", methods={"GET"})
*/
public function index(RegistrationRequestRepository $registrationRequestRepository): Response
{
return $this->render('registration_request/index.html.twig', [
'registration_requests' => $registrationRequestRepository->findAll(),
]);
}
/**
* #Route("/{_locale<%app.supported_locales%>}/new", name="app_registration_request_new", methods={"GET", "POST"})
*/
public function new(Request $request, RegistrationRequestRepository $registrationRequestRepository, IGSNService $igsnService, TranslatorInterface $translator): Response
{
$registrationRequest = new RegistrationRequest();
$form = $this->createForm(RegistrationRequestType::class, $registrationRequest);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$json_data = json_decode($registrationRequest->getData());
$err = $igsnService->validate_data($json_data);
if ($json_data !== null && empty($err)) {
$registrationRequestRepository->add($registrationRequest, true);
$this->addFlash(
'success',
$translator->trans('Your changes were saved!')
);
return $this->redirectToRoute('app_registration_request_index', [], Response::HTTP_SEE_OTHER);
} else {
$this->addFlash(
'schema_error',
$err
);
}
}
return $this->renderForm('registration_request/new.html.twig', [
'registration_request' => $registrationRequest,
'form' => $form,
]);
}
/**
* #Route("/{_locale<%app.supported_locales%>}/{id}", name="app_registration_request_show", methods={"GET"})
*/
public function show(RegistrationRequest $registrationRequest): Response
{
return $this->render('registration_request/show.html.twig', [
'registration_request' => $registrationRequest,
]);
}
/**
* #Route("/{_locale<%app.supported_locales%>}/{id}/edit", name="app_registration_request_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, RegistrationRequest $registrationRequest, RegistrationRequestRepository $registrationRequestRepository, IGSNService $igsnService, TranslatorInterface $translator): Response
{
$form = $this->createForm(RegistrationRequestType::class, $registrationRequest);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$json_data = json_decode($registrationRequest->getData());
$err = $igsnService->validate_data($json_data);
if ($json_data !== null && empty($err)) {
$registrationRequestRepository->add($registrationRequest, true);
$this->addFlash(
'success',
$translator->trans('Your changes were saved!')
);
return $this->redirectToRoute('app_registration_request_index', [], Response::HTTP_SEE_OTHER);
} else {
$this->addFlash(
'schema_error',
$err
);
}
}
return $this->renderForm('registration_request/edit.html.twig', [
'registration_request' => $registrationRequest,
'form' => $form,
]);
}
/**
* #Route("/{_locale<%app.supported_locales%>}/{id}", name="app_registration_request_delete", methods={"POST"})
*/
public function delete(Request $request, RegistrationRequest $registrationRequest, RegistrationRequestRepository $registrationRequestRepository, TranslatorInterface $translator): Response
{
if ($this->isCsrfTokenValid('delete' . $registrationRequest->getId(), $request->request->get('_token'))) {
$registrationRequestRepository->remove($registrationRequest, true);
$this->addFlash(
'success',
$translator->trans('Request successfully deleted!')
);
}
return $this->redirectToRoute('app_registration_request_index', [], Response::HTTP_SEE_OTHER);
}
}
config/packages/api_platform.yaml
api_platform:
mapping:
paths: ['%kernel.project_dir%/src/Entity']
patch_formats:
json: ['application/merge-patch+json']
swagger:
versions: [3]
# Fixes empty api endpoint list with error:
# No operations defined in spec!
# See https://github.com/api-platform/core/issues/4485
metadata_backward_compatibility_layer: false
I have now got it solved with a DataPersister, as suggested by Julien B. in the comments.
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
use App\Entity\RegistrationRequest;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
final class RequestDataPersister implements DataPersisterInterface
{
private $security;
public function __construct(Security $security, EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
$this->security = $security;
}
public function supports($data): bool
{
return $data instanceof RegistrationRequest;
}
public function persist($data)
{
$data->setUser($this->security->getUser());
$this->entityManager->persist($data);
$this->entityManager->flush();
return $data;
}
public function remove($data): void
{
// no action needed
}
}
I tried to upload images in my database with Symfony 5 and Vichuploader bundle but my filename is not persisted in my database and I don't know why.
This the error that I have : An exception occurred while executing a query: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'filename' cannot be null
This is my entity Person.php :
namespace App\Entity;
use App\Repository\PersonRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass=PersonRepository::class)
*/
class Person
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="datetime")
*/
private $birthDate;
/**
* #ORM\ManyToMany(targetEntity=Movie::class, mappedBy="writers")
*/
public $writedMovies;
/**
* #ORM\ManyToMany(targetEntity=Movie::class, mappedBy="directors")
*/
private $directedMovies;
/**
* #ORM\ManyToMany(targetEntity=Movie::class, mappedBy="producers")
*/
private $producedMovies;
/**
* #ORM\OneToMany(targetEntity=MovieActor::class, mappedBy="person", orphanRemoval=true, cascade={"persist"})
*/
private $movieActors;
/**
* #ORM\Column(type="boolean")
*/
private $sex;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $pseudo;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
private $deathDate;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $firstname;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $middleName;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $biography;
/**
* #ORM\OneToMany(targetEntity=MovieMusicComposer::class, mappedBy="person")
*/
private $movieMusicComposers;
/**
* #ORM\OneToMany(targetEntity=AwardPerson::class, mappedBy="person")
*/
private $awardPeople;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $award1;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $award2;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $award3;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $award4;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $award5;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $award6;
/**
* #ORM\Column(type="string", length=100, nullable=true)
*/
private $nationality;
/**
* #ORM\OneToMany(targetEntity=PicturePerson::class, mappedBy="person", orphanRemoval=true, cascade={"persist"})
*/
private $picturePeople;
/**
* #Assert\All({
* #Assert\Image(mimeTypes="image/jpeg")
* })
*/
private $pictureFiles;
/**
* #ORM\Column(type="datetime")
*/
private $created_at;
/**
* #ORM\Column(type="datetime")
*/
private $updated_at;
public function __construct()
{
$this->writedMovies = new ArrayCollection();
$this->movieActors = new ArrayCollection();
$this->movieMusicComposers = new ArrayCollection();
$this->awardPeoples = new ArrayCollection();
$this->directedMovies = new ArrayCollection();
$this->producedMovies = new ArrayCollection();
$this->awardPeople = new ArrayCollection();
$this->picturePeople = new ArrayCollection();
$this->created_at = new \DateTime();
$this->updated_at = new \DateTime();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getBirthDate(): ?\DateTimeInterface
{
return $this->birthDate;
}
public function setBirthDate(\DateTimeInterface $birthDate): self
{
$this->birthDate = $birthDate;
return $this;
}
/**
* #return Collection|Movie[]
*/
public function getWritedMovies(): Collection
{
return $this->writedMovies;
}
public function addWritedMovie(Movie $writedMovie): self
{
if (!$this->writedMovies->contains($writedMovie)) {
$this->writedMovies[] = $writedMovie;
}
return $this;
}
public function removeWritedMovie(Movie $writedMovie): self
{
$this->writedMovies->removeElement($writedMovie);
return $this;
}
/**
* #return Collection|MovieActor[]
*/
public function getMovieActors(): Collection
{
return $this->movieActors;
}
public function addMovieActor(MovieActor $movieActor): self
{
if (!$this->movieActors->contains($movieActor)) {
$this->movieActors[] = $movieActor;
$movieActor->setPerson($this);
}
return $this;
}
public function removeMovieActor(MovieActor $movieActor): self
{
if ($this->movieActors->removeElement($movieActor)) {
// set the owning side to null (unless already changed)
if ($movieActor->getPerson() === $this) {
$movieActor->setPerson(null);
}
}
return $this;
}
public function getSex(): ?bool
{
return $this->sex;
}
public function setSex(bool $sex): self
{
$this->sex = $sex;
return $this;
}
public function getPseudo(): ?string
{
return $this->pseudo;
}
public function setPseudo(?string $pseudo): self
{
$this->pseudo = $pseudo;
return $this;
}
public function getDeathDate(): ?\DateTimeInterface
{
return $this->deathDate;
}
public function setDeathDate(?\DateTimeInterface $deathDate): self
{
$this->deathDate = $deathDate;
return $this;
}
public function getFirstname(): ?string
{
return $this->firstname;
}
public function setFirstname(?string $firstname): self
{
$this->firstname = $firstname;
return $this;
}
public function getMiddleName(): ?string
{
return $this->middleName;
}
public function setMiddleName(string $middleName): self
{
$this->middleName = $middleName;
return $this;
}
public function getBiography(): ?string
{
return $this->biography;
}
public function setBiography(?string $biography): self
{
$this->biography = $biography;
return $this;
}
/**
* #return Collection|MovieMusicComposer[]
*/
public function getMovieMusicComposers(): Collection
{
return $this->movieMusicComposers;
}
public function addMovieMusicComposer(MovieMusicComposer $movieMusicComposer): self
{
if (!$this->movieMusicComposers->contains($movieMusicComposer)) {
$this->movieMusicComposers[] = $movieMusicComposer;
$movieMusicComposer->setPerson($this);
}
return $this;
}
public function removeMovieMusicComposer(MovieMusicComposer $movieMusicComposer): self
{
if ($this->movieMusicComposers->removeElement($movieMusicComposer)) {
// set the owning side to null (unless already changed)
if ($movieMusicComposer->getPerson() === $this) {
$movieMusicComposer->setPerson(null);
}
}
return $this;
}
/**
* #return Collection|Movie[]
*/
public function getDirectedMovies(): Collection
{
return $this->directedMovies;
}
public function addDirectedMovie(Movie $directedMovie): self
{
if (!$this->directedMovies->contains($directedMovie)) {
$this->directedMovies[] = $directedMovie;
$directedMovie->addDirector($this);
}
return $this;
}
public function removeDirectedMovie(Movie $directedMovie): self
{
if ($this->directedMovies->removeElement($directedMovie)) {
$directedMovie->removeDirector($this);
}
return $this;
}
/**
* #return Collection|Movie[]
*/
public function getProducedMovies(): Collection
{
return $this->producedMovies;
}
public function addProducedMovie(Movie $producedMovie): self
{
if (!$this->producedMovies->contains($producedMovie)) {
$this->producedMovies[] = $producedMovie;
$producedMovie->addProducer($this);
}
return $this;
}
public function removeProducedMovie(Movie $producedMovie): self
{
if ($this->producedMovies->removeElement($producedMovie)) {
$producedMovie->removeProducer($this);
}
return $this;
}
/**
* #return Collection|AwardPerson[]
*/
public function getAwardPeople(): Collection
{
return $this->awardPeople;
}
public function addAwardPerson(AwardPerson $awardPerson): self
{
if (!$this->awardPeople->contains($awardPerson)) {
$this->awardPeople[] = $awardPerson;
$awardPerson->setPerson($this);
}
return $this;
}
public function removeAwardPerson(AwardPerson $awardPerson): self
{
if ($this->awardPeople->removeElement($awardPerson)) {
// set the owning side to null (unless already changed)
if ($awardPerson->getPerson() === $this) {
$awardPerson->setPerson(null);
}
}
return $this;
}
public function getAward1(): ?string
{
return $this->award1;
}
public function setAward1(?string $award1): self
{
$this->award1 = $award1;
return $this;
}
public function getAward2(): ?string
{
return $this->award2;
}
public function setAward2(?string $award2): self
{
$this->award2 = $award2;
return $this;
}
public function getAward3(): ?string
{
return $this->award3;
}
public function setAward3(?string $award3): self
{
$this->award3 = $award3;
return $this;
}
public function getAward4(): ?string
{
return $this->award4;
}
public function setAward4(?string $award4): self
{
$this->award4 = $award4;
return $this;
}
public function getAward5(): ?string
{
return $this->award5;
}
public function setAward5(?string $award5): self
{
$this->award5 = $award5;
return $this;
}
public function getAward6(): ?string
{
return $this->award6;
}
public function setAward6(?string $award6): self
{
$this->award6 = $award6;
return $this;
}
public function getNationality(): ?string
{
return $this->nationality;
}
public function setNationality(?string $nationality): self
{
$this->nationality = $nationality;
return $this;
}
/**
* #return Collection|PicturePerson[]
*/
public function getPicturePeople(): Collection
{
return $this->picturePeople;
}
public function addPicturePerson(PicturePerson $picturePerson): self
{
if (!$this->picturePeople->contains($picturePerson)) {
$this->picturePeople[] = $picturePerson;
$picturePerson->setPerson($this);
}
return $this;
}
/**
* #return mixed
*/
public function getPictureFiles()
{
return $this->pictureFiles;
}
/**
* #param mixed $pictureFiles
* #return Person
*/
public function setPictureFiles($pictureFiles): self
{
foreach($pictureFiles as $pictureFile) {
$picture = new PicturePerson();
$picture->setImageFile($pictureFile);
$this->addPicturePerson($picture);
}
$this->pictureFiles = $pictureFiles;
return $this;
}
public function removePicturePerson(PicturePerson $picturePerson): self
{
if ($this->picturePeople->removeElement($picturePerson)) {
// set the owning side to null (unless already changed)
if ($picturePerson->getPerson() === $this) {
$picturePerson->setPerson(null);
}
}
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->created_at;
}
public function setCreatedAt(\DateTimeInterface $created_at): self
{
$this->created_at = $created_at;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updated_at;
}
public function setUpdatedAt(\DateTimeInterface $updated_at): self
{
$this->updated_at = $updated_at;
return $this;
}
}
This is my Entity PicturePerson.php :
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity(repositoryClass=PicturePersonRepository::class)
*/
class PicturePerson
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var File|null
* #Assert\Image(
* mimeTypes="image/jpeg"
* )
* #Vich\UploadableField(mapping="person_image", fileNameProperty="filename")
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255)
*/
private $filename;
/**
* #ORM\ManyToOne(targetEntity=Person::class, inversedBy="picturePeople")
* #ORM\JoinColumn(nullable=false)
*/
private $person;
public function getId(): ?int
{
return $this->id;
}
public function getFilename(): ?string
{
return $this->filename;
}
public function setFilename(?string $filename): self
{
$this->filename = $filename;
return $this;
}
public function getPerson(): ?Person
{
return $this->person;
}
public function setPerson(?Person $person): self
{
$this->person = $person;
return $this;
}
/**
* #return null|File
*/
public function getImageFile(): ?File
{
return $this->imageFile;
}
/**
* #param null|File $imageFile
* #return self
*/
public function setImageFile(?File $imageFile): self
{
$this->imageFile = $imageFile;
return $this;
}
}
This is my config file vich_uploader.yaml :
db_driver: orm
mappings:
movie_image:
uri_prefix: /images/movies
upload_destination: '%kernel.project_dir%/public/images/movies'
namer: Vich\UploaderBundle\Naming\UniqidNamer
movie_video:
uri_prefix: /videos/movies
upload_destination: '%kernel.project_dir%/public/videos/movies'
namer: Vich\UploaderBundle\Naming\UniqidNamer
movie_audio:
uri_prefix: /audios/movies
upload_destination: '%kernel.project_dir%/public/audios/movies'
namer: Vich\UploaderBundle\Naming\UniqidNamer
person_image:
uri_prefix: /images/person_image
upload_destination: '%kernel.project_dir%/public/images/person_image'
namer: Vich\UploaderBundle\Naming\UniqidNamer
This is my form PersonType.php:
namespace App\Form;
use App\Entity\Person;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('pseudo', TextType::class, [
"label" => "Pseudonyme",
"required" => false
])
->add('name', TextType::class, [
"label" => "Nom",
"required" => true
])
->add('firstname', TextType::class, [
"label" => "Prénom",
"required" => true
])
->add('middleName', TextType::class, [
"label" => "2ème Prénom",
"required" => false
])
->add('birthDate', BirthdayType::class, [
"widget" => "single_text",
"label" => "Date de naissance",
])
->add('deathDate', BirthdayType::class, [
"widget" => "single_text",
"label" => "Date de mort",
"required" => false
])
->add('sex', ChoiceType::class, [
"label" => "Genre",
'choices' => [
'Homme' => true,
'Femme' => false,
],
])
->add('nationality', TextType::class, [
'required' => false,
"label" => "Nationalité"
])
->add('award1', TextType::class, [
'required' => false,
"label" => "Récompense 1"
])
->add('award2', TextType::class, [
'required' => false,
"label" => "Récompense 2"
])
->add('award3', TextType::class, [
'required' => false,
"label" => "Récompense 3"
])
->add('award4', TextType::class, [
'required' => false,
"label" => "Récompense 4"
])
->add('award5', TextType::class, [
'required' => false,
"label" => "Récompense 5"
])
->add('award6', TextType::class, [
'required' => false,
"label" => "Récompense 6"
])
->add('pictureFiles', FileType::class, [
'required' => false,
'multiple' => true,
'label' => 'Chargement d\'images (jpeg uniquement) '
])
->add('biography', TextareaType::class, [
'required' => false,
"label" => "Biographie",
])
// ->add('awardPeople', TextType::class, [
// "label" => "Prix remporté(s)"
// ])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Person::class,
]);
}
}
When I try to registering a new user, I had this error
An exception occurred while executing 'INSERT INTO user (username, password, email, gender, newsletter, is_blocked, role_id, purchase_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)' with params ["momo", "$2y$13$qCw4ZjU6k4s/dIwTeseEVud/zdjVu3xVper8oHAqsd/fKihq05Ga2", "momo#test.fr", "1", 0, 0, null, null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'role_id' cannot be null
Thank's in advance.
Here is my User entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* * #UniqueEntity(
* fields = {"username"},
* message = "Le nom d'utilisateur existe déjà",
* )
* #UniqueEntity(
* fields = {"email"},
* message = "L'email existe déjà",
* )
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=180, unique=true)
*/
private $username;
private $roles = [];
/**
* #var string The hashed password
* #ORM\Column(type="string")
*/
private $password;
/**
* #ORM\Column(type="string", length=180, unique=true)
*/
private $email;
/**
* #ORM\Column(type="string", length=255)
*/
private $gender;
/**
* #ORM\Column(type="boolean", nullable=true)
*/
private $newsletter;
/**
* #ORM\Column(type="boolean")
*/
private $isBlocked;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Role", inversedBy="users")
* #ORM\JoinColumn(nullable=false)
*/
private $role;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Article", inversedBy="users")
*/
private $article;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Firmware", inversedBy="users")
*/
private $firmware;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Purchase", inversedBy="users")
*/
private $purchase;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Note", mappedBy="user",
orphanRemoval=true)
*/
private $notes;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="user",
orphanRemoval=true)
*/
private $comments;
public function __construct()
{
$this->article = new ArrayCollection();
$this->firmware = new ArrayCollection();
$this->notes = new ArrayCollection();
$this->comments = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUsername(): string
{
return (string) $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* #see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* #see UserInterface
*/
public function getSalt()
{
// not needed when using the "bcrypt" algorithm in security.yaml
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it
here
// $this->plainPassword = null;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getGender(): ?string
{
return $this->gender;
}
public function setGender(string $gender): self
{
$this->gender = $gender;
return $this;
}
public function getNewsletter(): ?bool
{
return $this->newsletter;
}
public function setNewsletter(bool $newsletter): self
{
$this->newsletter = $newsletter;
return $this;
}
public function getIsBlocked(): ?bool
{
return $this->isBlocked;
}
public function setIsBlocked(bool $isBlocked): self
{
$this->isBlocked = $isBlocked;
return $this;
}
public function getRole(): ?Role
{
return $this->role;
}
public function setRole(?Role $role): self
{
$this->role = $role;
return $this;
}
/**
* #return Collection|Article[]
*/
public function getArticle(): Collection
{
return $this->article;
}
public function addArticle(Article $article): self
{
if (!$this->article->contains($article)) {
$this->article[] = $article;
}
return $this;
}
public function removeArticle(Article $article): self
{
if ($this->article->contains($article)) {
$this->article->removeElement($article);
}
return $this;
}
/**
* #return Collection|Firmware[]
*/
public function getFirmware(): Collection
{
return $this->firmware;
}
public function addFirmware(Firmware $firmware): self
{
if (!$this->firmware->contains($firmware)) {
$this->firmware[] = $firmware;
}
return $this;
}
public function removeFirmware(Firmware $firmware): self
{
if ($this->firmware->contains($firmware)) {
$this->firmware->removeElement($firmware);
}
return $this;
}
public function getPurchase(): ?Purchase
{
return $this->purchase;
}
public function setPurchase(?Purchase $purchase): self
{
$this->purchase = $purchase;
return $this;
}
/**
* #return Collection|Note[]
*/
public function getNotes(): Collection
{
return $this->notes;
}
public function addNote(Note $note): self
{
if (!$this->notes->contains($note)) {
$this->notes[] = $note;
$note->setUser($this);
}
return $this;
}
public function removeNote(Note $note): self
{
if ($this->notes->contains($note)) {
$this->notes->removeElement($note);
// set the owning side to null (unless already changed)
if ($note->getUser() === $this) {
$note->setUser(null);
}
}
return $this;
}
/**
* #return Collection|Comment[]
*/
public function getComments(): Collection
{
return $this->comments;
}
public function addComment(Comment $comment): self
{
if (!$this->comments->contains($comment)) {
$this->comments[] = $comment;
$comment->setUser($this);
}
return $this;
}
public function removeComment(Comment $comment): self
{
if ($this->comments->contains($comment)) {
$this->comments->removeElement($comment);
// set the owning side to null (unless already changed)
if ($comment->getUser() === $this) {
$comment->setUser(null);
}
}
return $this;
}
}
Role Entity
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\RoleRepository")
*/
class Role
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="string", length=255)
*/
private $description;
/**
* #ORM\OneToMany(targetEntity="App\Entity\User", mappedBy="role")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
/**
* #return Collection|User[]
*/
public function getUsers(): Collection
{
return $this->users;
}
public function addUser(User $user): self
{
if (!$this->users->contains($user)) {
$this->users[] = $user;
$user->setRole($this);
}
return $this;
}
public function removeUser(User $user): self
{
if ($this->users->contains($user)) {
$this->users->removeElement($user);
// set the owning side to null (unless already changed)
if ($user->getRole() === $this) {
$user->setRole(null);
}
}
return $this;
}
public function __toString()
{
return $this->name;
}
}
UserType
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array
$options)
{
$builder
->add('username', TextType::class, [
'empty_data' => '',
])
->add('password', RepeatedType::class, [
'type' => PasswordType::class,
'empty_data' => '',
'invalid_message' => 'Valeur no correcte',
'options' => ['attr' => ['class' => 'password-field']],
'required' => true,
'first_options' => ['label' => 'Password','empty_data' =>
''],
'second_options' => ['label' => 'Repeat Password','empty_data'
=> ''],
])
->add('email',EmailType::class, [
'empty_data' => '',
])
->add('gender', ChoiceType::class, [
'help' => 'Un choix possible',
'choices' => [
'Femme' => true,
'Homme' => true,
'Autre' => true,
],
])
->add('newsletter')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
SecutityController
<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\UserType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class SecurityController extends AbstractController
{
/**
* #Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', ['last_username' =>
$lastUsername, 'error' => $error]);
}
/**
* #Route("/inscription", name="registration")
*/
public function registration(Request $request, EntityManagerInterface $em,
UserPasswordEncoderInterface $passwordEncoder)
{
$user = new User();
// $role = $user->getRoles();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$password = $passwordEncoder->encodePassword($user, $user-
>getPassword());
$user->setPassword($password);
$user->setIsBlocked(false);
// $user->setRole($role);
$em->persist($user);
$em->flush();
$this->addFlash('success', 'Votre compte à bien été enregistré.');
}
return $this->render('security/registration.html.twig', ['form' =>
$form->createView()]);
}
/**
* #Route("/logout", name="logout")
*/
public function logout() {}
}
On role property Change nullable=false to nullable=true And update the database
* #ORM\JoinColumn(nullable=true)
*/
private $role;
I have form that user can change it is own email. But when validation error occured or some constrait failed session die and user is redirected to login page. Important to note that user is authenticated by user and password from database. Thanks for helping
UPDATE
I just added User.php file for more details.
namespace App\Form;
class ChangeEmailType extends AbstractType
{
private $translator;
private $transformer;
public function __construct(TranslatorInterface $translator, DateTimeToStringTransformer $transformer)
{
$this->transformer = $transformer;
$this->translator = $translator;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('email', EmailType::class, array(
'required' => true,
'label' => $this->translator->trans('email'),
'attr' => array('class' => 'form-control')
))
->add('updationDate', HiddenType::class, array(
'required' => true,
'label' => false,
));
$builder->get('updationDate')->addModelTransformer($this>transformer);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'App\Entity\User',
'attr' => array('class' => 'change-email-form')
));
}
}
UserController.php
/**
* #Security("has_role('ROLE_USER')")
* #Route("/profile/change-email", name="change email")
*/
public function changeEmail(Request $request)
{
$user = $this->getUser();
$form = $this->createForm(ChangeEmailType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
try
{
$this->entityManager->lock($this->getUser(), LockMode::OPTIMISTIC, $user->getUpdationDate());
$this->entityManager->flush();
$this->addFlash('success', $this->translator->trans('email_is_successfully_changed'));
return $this->redirectToRoute('dashboard');
}
catch (OptimisticLockException $exception)
{
$this->addFlash('success', $this->translator->trans('data_is_outdated_try_again'));
return $this->redirectToRoute('change email');
}
}
return $this->render('app/pages/profile/change-email.html.twig', array(
'form' => $form->createView()
));
}
User.php
namespace App\Entity;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* #ORM\HasLifecycleCallbacks()
* #ORM\Table(name="users")
* #UniqueEntity(fields={"email"})
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #Assert\Length(
* min = 6,
* minMessage = "Password should by at least 6 characters long",
* groups={"registration"}
* )
* #Assert\Type(
* type="alnum",
* message="Password should contains only numbers and letters",
* groups={"registration"}
* )
* #Assert\NotBlank()
* #ORM\Column(type="text", nullable=true)
*/
private $password;
/**
* #Assert\NotBlank(message="field_is_required")
* #Assert\Email(message="email_is_invalid")
* #ORM\Column(type="string", length=255, unique=true)
*/
private $email;
/**
* #ORM\Column(type="string", length=255)
*/
private $theme;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $facebookId;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $linkedinId;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $passwordRecoveryHash;
/**
* #ORM\Column(type="integer")
*/
private $status;
/**
* #ORM\Column(type="string", length=255)
*/
private $emailConfirmationHash;
/**
* #ORM\Column(type="datetime")
* #ORM\Version
*/
private $updationDate;
/**
* #ORM\Column(type="datetime")
*/
private $creationDate;
/**
* #ORM\PrePersist()
*/
public function prePersist(): void
{
$this->creationDate = new DateTime();
$this->theme = 'light';
$this->status = 0;
}
public function getRoles()
{
return ['ROLE_USER'];
}
public function getPassword()
{
return $this->password;
}
public function getSalt()
{
return 'salt';
}
public function getUsername()
{
return $this->email;
}
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
public function getId()
{
return $this->id;
}
public function setId($id): void
{
$this->id = $id;
}
public function setPassword($password): void
{
$this->password = $password;
}
public function getEmail()
{
return $this->email;
}
public function setEmail($email): void
{
$this->email = $email;
}
public function getUpdationDate()
{
return $this->updationDate;
}
public function setUpdationDate($updationDate): void
{
$this->updationDate = $updationDate;
}
public function getCreationDate()
{
return $this->creationDate;
}
public function setCreationDate($creationDate): void
{
$this->creationDate = $creationDate;
}
public function getTheme()
{
return $this->theme;
}
public function setTheme($theme): void
{
$this->theme = $theme;
}
public function getPasswordRecoveryHash()
{
return $this->passwordRecoveryHash;
}
public function setPasswordRecoveryHash($passwordRecoveryHash): void
{
$this->passwordRecoveryHash = $passwordRecoveryHash;
}
public function getFacebookId()
{
return $this->facebookId;
}
public function setFacebookId($facebookId): void
{
$this->facebookId = $facebookId;
}
public function getLinkedinId()
{
return $this->linkedinId;
}
public function setLinkedinId($linkedinId): void
{
$this->linkedinId = $linkedinId;
}
public function getEmailConfirmationHash()
{
return $this->emailConfirmationHash;
}
public function setEmailConfirmationHash($emailConfirmationHash): void
{
$this->emailConfirmationHash = $emailConfirmationHash;
}
public function getStatus()
{
return $this->status;
}
public function setStatus($status): void
{
$this->status = $status;
}
}
So I had the same problem but I fixed it by to not passing object User to the formType.
This is my code
$user = $this->getUser();
// don't pass pass $user as parameter
$form = $this->createForm(ChangeEmailType::class);
$form->handleRequest($request);
if ($form->isSubmitted()) {
$em = $this->getDoctrine()->getManager();
$currentEmail = $user->getEmail();
$newEmail = $form->get('email')->getData();
$currentPassword = $form->get('currentPassword')->getData();
// verify if the tow emails are different
if ($currentEmail === $newEmail) {
$form->get('email')->addError(new FormError('You must choose a different email.'));
}
// verify if the email is used by another user
$userHasAlreadyThisEmail = $em->getRepository('App:User')->findOneBy(array('email' => $newEmail));
if ($userHasAlreadyThisEmail && $userHasAlreadyThisEmail !== $user) {
$form->get('email')->addError(new FormError('This email is already used.'));
}
// verify if the password is correct
$verify = $this->verify($currentPassword, $user->getPassword());
if ($verify === false) {
$form->get('currentPassword')->addError(new FormError('Incorrect password.'));
}
if ($form->isValid()) {
$this->addFlash('success', 'The email has been successfully modified.');
$user->setEmail($newEmail);
$em->flush();
return $this->redirectToRoute('profile_change_email');
}
}
public function verify($input, $existingHash)
{
$hash = password_verify($input, $existingHash);
return $hash === true;
}