Hello guys I need help.
I'm trying to build a forum for my website in symfony.
I have an entity Theme who regroup the entity Slug who regroup the entity Post.
When I navigate to the slug route to see the posts, I have the error "Call to a member function getSlug() on null".
But this function is called in another route.
Here is my different entity.
Theme
<?php
namespace App\Entity;
use App\Repository\ThemeRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ThemeRepository::class)]
class Theme
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $name;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $imageName;
#[ORM\OneToMany(mappedBy: 'theme', targetEntity: Slug::class, orphanRemoval: true)]
private $slug;
public function __construct()
{
$this->slug = 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 getImageName(): ?string
{
return $this->imageName;
}
public function setImageName(?string $imageName): self
{
$this->imageName = $imageName;
return $this;
}
/**
* #return Collection<int, Slug>
*/
public function getSlug(): Collection
{
return $this->slug;
}
public function addSlug(Slug $slug): self
{
if (!$this->slug->contains($slug)) {
$this->slug[] = $slug;
$slug->setTheme($this);
}
return $this;
}
public function removeSlug(Slug $slug): self
{
if ($this->slug->removeElement($slug)) {
// set the owning side to null (unless already changed)
if ($slug->getTheme() === $this) {
$slug->setTheme(null);
}
}
return $this;
}
}
Slug
<?php
namespace App\Entity;
use App\Repository\SlugRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: SlugRepository::class)]
class Slug
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $slugName;
#[ORM\OneToMany(mappedBy: 'slug', targetEntity: Post::class, orphanRemoval: true)]
private $posts;
#[ORM\ManyToOne(targetEntity: Theme::class, inversedBy: 'slug')]
#[ORM\JoinColumn(nullable: false)]
private $theme;
public function __construct()
{
$this->posts = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getSlugName(): ?string
{
return $this->slugName;
}
public function setSlugName(string $slugName): self
{
$this->slugName = $slugName;
return $this;
}
/**
* #return Collection<int, Post>
*/
public function getPosts(): Collection
{
return $this->posts;
}
public function addPost(Post $post): self
{
if (!$this->posts->contains($post)) {
$this->posts[] = $post;
$post->setSlug($this);
}
return $this;
}
public function removePost(Post $post): self
{
if ($this->posts->removeElement($post)) {
// set the owning side to null (unless already changed)
if ($post->getSlug() === $this) {
$post->setSlug(null);
}
}
return $this;
}
public function getTheme(): ?Theme
{
return $this->theme;
}
public function setTheme(?Theme $theme): self
{
$this->theme = $theme;
return $this;
}
}
Post
<?php
namespace App\Entity;
use App\Repository\PostRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: PostRepository::class)]
class Post
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'text')]
private $content;
#[ORM\Column(type: 'datetime_immutable')]
private $createdAt;
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
private $updatedAt;
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'posts')]
#[ORM\JoinColumn(nullable: false)]
private $user;
#[ORM\ManyToOne(targetEntity: Slug::class, inversedBy: 'posts')]
#[ORM\JoinColumn(nullable: false)]
private $slug;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $imageName;
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeImmutable $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeImmutable
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getSlug(): ?Slug
{
return $this->slug;
}
public function setSlug(?Slug $slug): self
{
$this->slug = $slug;
return $this;
}
public function getImageName(): ?string
{
return $this->imageName;
}
public function setImageName(?string $imageName): self
{
$this->imageName = $imageName;
return $this;
}
}
And here is my controller
<?php
namespace App\Controller;
use App\Repository\SlugRepository;
use App\Repository\ThemeRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ForumController extends AbstractController
{
#[Route('/forum', name: 'forum')]
public function index(SlugRepository $slugRepository, ThemeRepository $themeRepository ): Response
{
$themes = $themeRepository->findAll();
return $this->render('forum/index.html.twig', [
'themes' => $themes,
]);
}
#[Route('/forum/{name}/{id}', name: 'theme')]
public function theme(string $name, $id, ThemeRepository $themeRepository ): Response
{
$themesId = $themeRepository->find($id);
$themes = $themeRepository->find($name);
$slugs = $themesId->getSlug();
$allThemes = $themeRepository->findAll();
return $this->render('forum/theme.html.twig', [
'themes' => $themesId,
'slugs' => $slugs,
'allThemes' => $allThemes,
]);
}
#[Route('/forum/{name}/{slugName}', name: 'slug')]
public function slug(string $name, string $slugName, $id,SlugRepository $slugRepository, ThemeRepository $themeRepository ): Response
{
$slugName = $slugRepository->find($slugName);
$slugsId = $slugRepository->find($id);
$themesId = $slugsId->getTheme()->getName($name);
$allThemes = $themeRepository->findAll();
return $this->render('forum/slug.html.twig', [
'themes' => $themesId,
'slugs' => $slugsId,
'allThemes' => $allThemes,
]);
}
}
I'm working on symfony 5.0.8
Thanks for your help.
In your method ForumController::theme the method $themeRepository->find() does not return a Theme object but null and $themes is unused.
$themesId = $themeRepository->find($id); // <- returns null
Solution: query by id and name explicitly.
$theme = $themeRepository->findOneBy([
'id' => $id,
'name' => $name
]);
if (!$theme) {
// log id and name, return a 404
}
$slug = $theme->getSlug();
Related
i want to create a user, but the user entity is connected to the entities role, address and personInfo, but i get the error that personInfo_id cannot be null? how do i pass in the id
i tried a value where i would manually pass the id, but that didn't work
This is my User entity
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: UserRepository::class)]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 30)]
private ?string $password = null;
#[ORM\OneToOne(inversedBy: 'User', cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(nullable: false)]
private ?Role $roleId = null;
#[ORM\OneToMany(mappedBy: 'UserId', targetEntity: PersonInfo::class, orphanRemoval: true, cascade:['persist'])]
private Collection $PersonInfoId;
#[ORM\ManyToOne(cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(nullable: false)]
private ?PersonInfo $personInfoId = null;
#[ORM\ManyToOne(inversedBy: 'UserId')]
#[ORM\JoinColumn(nullable: false)]
private ?Address $AddressId = null;
#[ORM\OneToMany(mappedBy: 'UserId', targetEntity: Address::class, orphanRemoval: true)]
private Collection $UserId;
public function __construct()
{
$this->PersonInfoId = new ArrayCollection();
$this->UserId = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getRoleId(): ?Role
{
return $this->roleId;
}
public function setRoleId(Role $roleId): self
{
$this->roleId = $roleId;
return $this;
}
/**
* #return Collection<int, PersonInfo>
*/
public function getPersonInfoId(): Collection
{
return $this->PersonInfoId;
}
public function addPersonInfoId(PersonInfo $personInfoId): self
{
if (!$this->PersonInfoId->contains($personInfoId)) {
$this->PersonInfoId->add($personInfoId);
$personInfoId->setUserId($this);
}
return $this;
}
public function removePersonInfoId(PersonInfo $personInfoId): self
{
if ($this->PersonInfoId->removeElement($personInfoId)) {
// set the owning side to null (unless already changed)
if ($personInfoId->getUserId() === $this) {
$personInfoId->setUserId(null);
}
}
return $this;
}
public function setPersonInfoId(?PersonInfo $personInfoId): self
{
$this->personInfoId = $personInfoId;
return $this;
}
public function getAddressId(): ?Address
{
return $this->AddressId;
}
public function setAddressId(?Address $AddressId): self
{
$this->AddressId = $AddressId;
return $this;
}
/**
* #return Collection<int, Address>
*/
public function getUserId(): Collection
{
return $this->UserId;
}
public function addUserId(Address $userId): self
{
if (!$this->UserId->contains($userId)) {
$this->UserId->add($userId);
$userId->setUserId($this);
}
return $this;
}
public function removeUserId(Address $userId): self
{
if ($this->UserId->removeElement($userId)) {
// set the owning side to null (unless already changed)
if ($userId->getUserId() === $this) {
$userId->setUserId(null);
}
}
return $this;
}
}
Role Entity
<?php
namespace App\Entity;
use App\Repository\RoleRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: RoleRepository::class)]
class Role
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 30)]
private ?string $name = null;
#[ORM\OneToOne(mappedBy: 'roleId', cascade: ['persist', 'remove'])]
private ?User $User = null;
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 getUser(): ?User
{
return $this->User;
}
public function setUser(User $User): self
{
// set the owning side of the relation if necessary
if ($User->getRoleId() !== $this) {
$User->setRoleId($this);
}
$this->User = $User;
return $this;
}
}
PersonInfo Entity :
<?php
namespace App\Entity;
use App\Repository\PersonInfoRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: PersonInfoRepository::class)]
class PersonInfo
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 30)]
private ?string $name = null;
#[ORM\Column(length: 30)]
private ?string $email = null;
#[ORM\Column]
private ?int $phone_number = null;
#[ORM\ManyToOne(inversedBy: 'PersonInfoId', cascade: ['persist'])]
#[ORM\JoinColumn(nullable: false)]
private ?User $UserId = null;
#[ORM\ManyToOne(inversedBy: 'addressId')]
#[ORM\JoinColumn(nullable: false)]
private ?Address $addressId = null;
#[ORM\OneToMany(mappedBy: 'personInfoId', targetEntity: ContactPersoon::class, orphanRemoval: true)]
private Collection $personInfoId;
public function __construct()
{
$this->personInfoId = 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 getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getPhoneNumber(): ?int
{
return $this->phone_number;
}
public function setPhoneNumber(int $phone_number): self
{
$this->phone_number = $phone_number;
return $this;
}
public function getUserId(): ?User
{
return $this->UserId;
}
public function setUserId(?User $UserId): self
{
$this->UserId = $UserId;
return $this;
}
public function getAddressId(): ?Address
{
return $this->addressId;
}
public function setAddressId(?Address $addressId): self
{
$this->addressId = $addressId;
return $this;
}
/**
* #return Collection<int, ContactPersoon>
*/
public function getPersonInfoId(): Collection
{
return $this->personInfoId;
}
public function addPersonInfoId(ContactPersoon $personInfoId): self
{
if (!$this->personInfoId->contains($personInfoId)) {
$this->personInfoId->add($personInfoId);
$personInfoId->setPersonInfoId($this);
}
return $this;
}
public function removePersonInfoId(ContactPersoon $personInfoId): self
{
if ($this->personInfoId->removeElement($personInfoId)) {
// set the owning side to null (unless already changed)
if ($personInfoId->getPersonInfoId() === $this) {
$personInfoId->setPersonInfoId(null);
}
}
return $this;
}
}
This is the erd that i designed if that may help with building the pictureThe ERD
please help
In class User and class PersonInfo both entity has nullable=false field mapping so you must need to pass object when you are creating user. For example:
$user = new User();
$personInfo = new PersonInfo();
$user->addPersonInfoId($personInfo); // Here argument must be object of PersonInfo instead of Id.
$em->persist($user);
$em->flush();
The roles of my user entity aren't save well in database.
I have a basic question but I didn't find the solution so I'm asking it myself here.
When I create an user he he's register with the role ROLE_USER. But in my database he's save as a:0:{}
Do you have an idea of what I can do to store them as [] by default.
Ok here is my user entity:
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`', options:["collate"=>"utf8mb4_unicode_ci", "charset"=>"utf8mb4"])]
#[UniqueEntity(fields: ['mail'], message: 'There is already an account with this mail.')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::ARRAY, nullable: true)]
private array $roles = [];
#[ORM\Column(length: 255)]
private ?string $username = null;
#[ORM\Column(length: 255)]
private ?string $password = null;
#[ORM\Column(length: 255)]
private ?string $group_role = null;
#[ORM\Column(length: 255)]
private ?string $mail = null;
#[ORM\Column(length: 255)]
private ?string $firstname = null;
#[ORM\Column(length: 255)]
private ?string $lastname = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE, options: ['default' => 'CURRENT_TIMESTAMP'])]
private ?\DateTime $create_datetime = null;
#[ORM\Column(length: 255)]
private ?string $notif_rule = null;
#[ORM\OneToMany(mappedBy: 'his_user', targetEntity: Logs::class, orphanRemoval: true)]
private Collection $logs;
#[ORM\OneToMany(mappedBy: 'his_user', targetEntity: Session::class)]
private Collection $sessions;
#[ORM\OneToMany(mappedBy: 'his_user', targetEntity: Access::class, orphanRemoval: true)]
private Collection $accesses;
public function __construct()
{
$this->logs = new ArrayCollection();
$this->sessions = new ArrayCollection();
$this->accesses = new ArrayCollection();
$this->create_datetime = new \DateTime( );
}
public function getId(): ?int
{
return $this->id;
}
/**
* #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;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getGroupRole(): ?string
{
return $this->group_role;
}
public function setGroupRole(string $group_role): self
{
$this->group_role = $group_role;
return $this;
}
public function getMail(): ?string
{
return $this->mail;
}
public function setMail(string $mail): self
{
$this->mail = $mail;
return $this;
}
public function getFirstname(): ?string
{
return $this->firstname;
}
public function setFirstname(string $firstname): self
{
$this->firstname = $firstname;
return $this;
}
public function getLastname(): ?string
{
return $this->lastname;
}
public function setLastname(string $lastname): self
{
$this->lastname = $lastname;
return $this;
}
public function getCreateDatetime(): ?\DateTimeInterface
{
return $this->create_datetime;
}
public function setCreateDatetime(\DateTimeInterface $create_datetime): self
{
$this->create_datetime = $create_datetime;
return $this;
}
public function getNotifRule(): ?string
{
return $this->notif_rule;
}
public function setNotifRule(string $notif_rule): self
{
$this->notif_rule = $notif_rule;
return $this;
}
/**
* #return Collection<int, Logs>
*/
public function getLogs(): Collection
{
return $this->logs;
}
public function addLog(Logs $log): self
{
if (!$this->logs->contains($log)) {
$this->logs->add($log);
$log->setHisUser($this);
}
return $this;
}
public function removeLog(Logs $log): self
{
if ($this->logs->removeElement($log)) {
// set the owning side to null (unless already changed)
if ($log->getHisUser() === $this) {
$log->setHisUser(null);
}
}
return $this;
}
/**
* #return Collection<int, Session>
*/
public function getSessions(): Collection
{
return $this->sessions;
}
public function addSession(Session $session): self
{
if (!$this->sessions->contains($session)) {
$this->sessions->add($session);
$session->setHisUser($this);
}
return $this;
}
public function removeSession(Session $session): self
{
if ($this->sessions->removeElement($session)) {
// set the owning side to null (unless already changed)
if ($session->getHisUser() === $this) {
$session->setHisUser(null);
}
}
return $this;
}
/**
* #return Collection<int, Access>
*/
public function getAccesses(): Collection
{
return $this->accesses;
}
public function addAccess(Access $access): self
{
if (!$this->accesses->contains($access)) {
$this->accesses->add($access);
$access->setHisUser($this);
}
return $this;
}
public function removeAccess(Access $access): self
{
if ($this->accesses->removeElement($access)) {
// set the owning side to null (unless already changed)
if ($access->getHisUser() === $this) {
$access->setHisUser(null);
}
}
return $this;
}
/**
* A visual identifier that represents this user
*
* #see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->mail;
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
}
And here is my route:
#[Route('/register', name: 'app_register')]
public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher, UserAuthenticatorInterface $userAuthenticator, UserAuthenticator $authenticator, EntityManagerInterface $entityManager): Response
{
$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// encode the plain password
$user->setPassword(
$userPasswordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
)
);
$entityManager->persist($user);
$entityManager->flush();
// do anything else you need here, like send an email
return $userAuthenticator->authenticateUser(
$user,
$authenticator,
$request
);
}
return $this->render('registration/register.html.twig', [
'registrationForm' => $form->createView(),
]);
}
Sorry the code is not properly formated I copy past it and it came that way.
The problem
Hi everybody ! I'm new on stackoverflow and in symfony. Before I came here, i've tried some solutions like create validator or insert functions directly in my entity or repository and call them into my CrudController but I still block...
I've 7 entities : User, Hideout, Agent, Contact, Mission, Speciality and Target (it's for a dummy project for training myself) and I use easyadmin to have CRUD on all of them.
Everything works well but in my MissionCrudController, I need to specify error if contact's nationality is different of the mission's country for example. And I don't know how I can do that without make a form by myself. I even don't know how to use Validators to help me.
Or maybe the solution is to create filters ? When user enters the mission's country, contacts from this country will be display ?
Maybe someone can explain it to me ?
Thanks in advance !
(And sorry for my english !)
And this is my code :
MissionCrudController.php
<?php
namespace App\Controller\Admin;
use App\Entity\Mission;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\CountryField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class MissionCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Mission::class;
}
public function configureFields(string $pageName): iterable
{
return [
TextField::new('title'),
TextareaField::new('description')->hideOnIndex(),
ChoiceField::new('type')->setChoices([
'Murder' => 'Murder',
'Surveillance' => 'Surveillance',
'Infiltration' => 'Infiltration',
'Kidnapping' => 'Kidnapping',
'Extraction' => 'Extraction',
]),
CountryField::new('country'),
DateField::new('startDate')->hideOnIndex(),
DateField::new('endDate')->hideOnIndex(),
AssociationField::new('speciality')->hideOnIndex(),
AssociationField::new('agent')->setRequired(true),
AssociationField::new('target')->setRequired(true),
AssociationField::new('contact')->setRequired(true),
AssociationField::new('hideout'),
ChoiceField::new('status')->setChoices([
'Preparation' => 'Preparation',
'Started' => 'Started',
'Finished' => 'Finished',
'Failed' => 'Failed',
]),
];
}
public function configureCrud(Crud $crud): Crud
{
return $crud
->setPageTitle('index', 'Missions');
}
}
Contact.php
<?php
namespace App\Entity;
use App\Repository\ContactRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ContactRepository::class)]
class Contact
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column()]
private ?int $id = null;
#[ORM\Column(length: 100)]
private ?string $firstname = null;
#[ORM\Column(length: 100)]
private ?string $lastname = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $dateOfBirth = null;
#[ORM\Column(length: 100)]
private ?string $codeName = null;
#[ORM\Column(length: 100)]
private ?string $nationality = null;
#[ORM\ManyToMany(targetEntity: Mission::class, mappedBy: 'contact')]
private Collection $missions;
public function __construct()
{
$this->missions = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getFirstname(): ?string
{
return $this->firstname;
}
public function setFirstname(string $firstname): self
{
$this->firstname = $firstname;
return $this;
}
public function getLastname(): ?string
{
return $this->lastname;
}
public function setLastname(string $lastname): self
{
$this->lastname = $lastname;
return $this;
}
public function getDateOfBirth(): ?\DateTimeInterface
{
return $this->dateOfBirth;
}
public function setDateOfBirth(\DateTimeInterface $dateOfBirth): self
{
$this->dateOfBirth = $dateOfBirth;
return $this;
}
public function getCodeName(): ?string
{
return $this->codeName;
}
public function setCodeName(string $codeName): self
{
$this->codeName = $codeName;
return $this;
}
public function getNationality(): ?string
{
return $this->nationality;
}
public function setNationality(string $nationality): self
{
$this->nationality = $nationality;
return $this;
}
/**
* #return Collection<int, Mission>
*/
public function getMissions(): Collection
{
return $this->missions;
}
public function addMission(Mission $mission): self
{
if (!$this->missions->contains($mission)) {
$this->missions[] = $mission;
$mission->addContact($this);
}
return $this;
}
public function removeMission(Mission $mission): self
{
if ($this->missions->removeElement($mission)) {
$mission->removeContact($this);
}
return $this;
}
public function __toString()
{
return $this->getCodeName();
}
}
Mission.php
<?php
namespace App\Entity;
use App\Repository\MissionRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: MissionRepository::class)]
class Mission
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column()]
private ?int $id = null;
#[ORM\Column(length: 100)]
private ?string $title = null;
#[ORM\Column(type: Types::TEXT)]
private ?string $description = null;
#[ORM\Column(length: 100)]
private ?string $country = null;
#[ORM\ManyToMany(targetEntity: Agent::class, inversedBy: 'missions')]
#[ORM\JoinColumn(nullable: false, onDelete: 'cascade')]
private Collection $agent;
#[ORM\ManyToMany(targetEntity: Contact::class, inversedBy: 'missions')]
#[ORM\JoinColumn(nullable: false, onDelete: 'cascade')]
private Collection $contact;
#[ORM\ManyToMany(targetEntity: Target::class, inversedBy: 'missions')]
#[ORM\JoinColumn(nullable: false, onDelete: 'cascade')]
private Collection $target;
#[ORM\ManyToMany(targetEntity: Hideout::class, inversedBy: 'missions')]
#[ORM\JoinColumn(nullable: false, onDelete: 'cascade')]
private Collection $hideout;
#[ORM\Column(length: 100)]
private ?string $type = null;
#[ORM\Column(length: 100)]
private ?string $status = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $startDate = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $endDate = null;
#[ORM\ManyToOne(inversedBy: 'missions')]
private ?Speciality $speciality = null;
public function __construct()
{
$this->agent = new ArrayCollection();
$this->contact = new ArrayCollection();
$this->target = new ArrayCollection();
$this->hideout = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getCountry(): ?string
{
return $this->country;
}
public function setCountry(string $country): self
{
$this->country = $country;
return $this;
}
/**
* #return Collection<int, Agent>
*/
public function getAgent(): Collection
{
return $this->agent;
}
public function addAgent(Agent $agent): self
{
if (!$this->agent->contains($agent)) {
$this->agent[] = $agent;
}
return $this;
}
public function removeAgent(Agent $agent): self
{
$this->agent->removeElement($agent);
return $this;
}
/**
* #return Collection<int, Contact>
*/
public function getContact(): Collection
{
return $this->contact;
}
public function addContact(Contact $contact): self
{
if (!$this->contact->contains($contact)) {
$this->contact[] = $contact;
}
return $this;
}
public function removeContact(Contact $contact): self
{
$this->contact->removeElement($contact);
return $this;
}
/**
* #return Collection<int, Target>
*/
public function getTarget(): Collection
{
return $this->target;
}
public function addTarget(Target $target): self
{
if (!$this->target->contains($target)) {
$this->target[] = $target;
}
return $this;
}
public function removeTarget(Target $target): self
{
$this->target->removeElement($target);
return $this;
}
/**
* #return Collection<int, Hideout>
*/
public function getHideout(): Collection
{
return $this->hideout;
}
public function addHideout(Hideout $hideout): self
{
if (!$this->hideout->contains($hideout)) {
$this->hideout[] = $hideout;
}
return $this;
}
public function removeHideout(Hideout $hideout): self
{
$this->hideout->removeElement($hideout);
return $this;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getStartDate(): ?\DateTimeInterface
{
return $this->startDate;
}
public function setStartDate(\DateTimeInterface $startDate): self
{
$this->startDate = $startDate;
return $this;
}
public function getEndDate(): ?\DateTimeInterface
{
return $this->endDate;
}
public function setEndDate(\DateTimeInterface $endDate): self
{
$this->endDate = $endDate;
return $this;
}
public function getSpeciality(): ?Speciality
{
return $this->speciality;
}
public function setSpeciality(?Speciality $speciality): self
{
$this->speciality = $speciality;
return $this;
}
I have two entities - one is Product, second - Order. I've created controllers to navigate between page of ProductController that lists the whole ProductRepository to the page of OrderController, which should:
take a Product ID to show its properties on the Order page (name and price)
have a form with quantity and "customer's" email to be added to the Order
calculate the price x quantity and add to the Order
I can't figure how to access the passed project's properties. I am able to access it via addProduct method of the Order entity, but cannot reach them to show them in twig nor manipulate them on variables as described above.
I'm sure it's a simple stuff but I am not sure even how to ask google the right way on this.
we click on a product from ProductRepository with
<a href="{{ path('app_order', {id: product.id}) }}">
and we go to OrderController
OrderController:
<?php
namespace App\Controller;
class OrderController extends AbstractController
{
#[Route('/order', name: 'app_order')]
public function addToOrder(ManagerRegistry $doctrine, Request $request, EntityManagerInterface $em): Response
{
$orderedProductId = (int) ($request->query->get('id'));
$pPrice = 1;
$order = new Order();
$order->addProduct($doctrine->getRepository(Product::class)->find($orderedProductId));
$form = $this->createFormBuilder($order)
->add('clientEmail', TextType::class)
->add('quantity', IntegerType::class)
->add('makeOrder', SubmitType::class, ['label' => 'Make Order'])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//$data = $form->getData();
$order->setStatus("Pending");
$order->setTotalSum(1);
$em->persist($order);
$em->flush();
}
return $this->render('order/index.html.twig', [
'form'=> $form->createView(),
'order'=> $order
]);
}
}
The entities look like this:
Product
<?php
namespace App\Entity;
use App\Repository\ProductRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string')]
private $name;
#[ORM\Column(type: 'integer')]
private $price;
#[ORM\Column(type: 'boolean')]
private $visible;
#[ORM\ManyToOne(targetEntity: Order::class, inversedBy: 'product')]
private $orderIds;
public function getId(): ?int
{
return $this->id;
}
public function getPrice(): ?int
{
return $this->price;
}
public function setPrice(int $price): self
{
$this->price = $price;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function isVisible(): ?bool
{
return $this->visible;
}
public function setVisible(bool $visible): self
{
$this->visible = $visible;
return $this;
}
public function getOrderIds(): ?Order
{
return $this->orderIds;
}
public function setOrderIds(?Order $orderIds): self
{
$this->orderIds = $orderIds;
return $this;
}
}
Order:
<?php
namespace App\Entity;
use App\Repository\OrderRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: OrderRepository::class)]
#[ORM\Table(name: '`order`')]
class Order
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'integer')]
private $totalSum;
#[ORM\Column(type: 'string', length: 255)]
private $status;
#[ORM\Column(type: 'integer')]
private $quantity;
#[ORM\OneToMany(mappedBy: 'orderIds', targetEntity: Product::class)]
private $product;
#[ORM\Column(type: 'string', length: 255)]
private $clientEmail;
public function __construct()
{
$this->product = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getTotalSum(): ?int
{
return $this->totalSum;
}
public function setTotalSum(int $totalSum): self
{
$this->totalSum = $totalSum;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getQuantity(): ?int
{
return $this->quantity;
}
public function setQuantity(int $quantity): self
{
$this->quantity = $quantity;
return $this;
}
/**
* #return Collection<int, Product>
*/
public function getProduct(): Collection
{
return $this->product;
}
public function addProduct(Product $product): self
{
if (!$this->product->contains($product)) {
$this->product[] = $product;
$product->setOrderIds($this);
}
return $this;
}
public function removeProduct(Product $product): self
{
if ($this->product->removeElement($product)) {
// set the owning side to null (unless already changed)
if ($product->getOrderIds() === $this) {
$product->setOrderIds(null);
}
}
return $this;
}
public function getClientEmail(): ?string
{
return $this->clientEmail;
}
public function setClientEmail(string $clientEmail): self
{
$this->clientEmail = $clientEmail;
return $this;
}
}
OK I got this.
Changed a property taken by OrderController from EntityManager to ProductRepository, then
$product= $productRepository->find($orderedProductId);
also: this is helpful: Getting only ID from entity relations without fetching whole object in Doctrine
solved!
I develop a site where an user can add a tag on his profile.
So to make this feature, I add this script on my controller:
if ($formTag->isSubmitted() && $formTag->isValid()) {
$dataFormTag = $formTag->getData();
$userTagsAssocied = $user->getTags();
$userTagsAssociedArray = $userTagsAssocied->toArray();
if (in_array($dataFormTag->getName(), $userTagsAssociedArray)) {
$this->addFlash('danger', 'Vous avez deja le tag ' . $dataFormTag->getName() . ' associé à votre profil');
return $this->redirectToRoute('app_user_profil');
}
$user->addTag($dataFormTag);
$this->entityManager->persist($user);
$this->entityManager->flush();
$this->addFlash('success', 'Tag ' . $dataFormTag->getName() . ' bien lier à votre profil');
return $this->redirectToRoute('app_user_profil');
}
That work ! but the problem, is that duplicate the tag in my tag database.
An user who's add the tag FPS on his profil, the tag gonna be duplicate on bdd:
I add one of the 5 tag n my profil ( for exemple FPS)
The tag FPS is correctly added on my profil
But now, the Tag FPS is duplicate on my database and I show him to my select input..
here my user entity :
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 180, unique: true)]
private $email;
#[ORM\Column(type: 'json')]
private $roles = [];
#[ORM\Column(type: 'string')]
private $password;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $discord;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $twitter;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $instagram;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $tiktok;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $facebook;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $twitch;
#[ORM\Column(type: 'string', length:255)]
private $img;
#[ORM\Column(type: 'string', length: 255)]
private $pseudo;
#[ORM\Column(type:'text', nullable: true)]
private $description;
#[ORM\Column(type: 'datetime')]
private $created_time;
#[ORM\Column(type: 'datetime')]
private $updated_time;
#[ORM\ManyToMany(targetEntity: Tag::class, inversedBy: 'users', cascade: ['persist'])]
private $tags;
#[ORM\ManyToMany(targetEntity: Games::class, inversedBy: 'users', cascade: ['persist'])]
private $games;
#[ORM\Column(type: 'boolean')]
private $isVerified = false;
public function __construct()
{
$this->tags = new ArrayCollection();
$this->games = new ArrayCollection();
$this->created_time = new \DateTime();
$this->updated_time = new \DateTime();
}
public function __toString()
{
return $this->pseudo;
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
/**
* #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 PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getDiscord(): ?string
{
return $this->discord;
}
public function setDiscord(?string $discord): self
{
$this->discord = $discord;
return $this;
}
public function getTwitter(): ?string
{
return $this->twitter;
}
public function setTwitter(?string $twitter): self
{
$this->twitter = $twitter;
return $this;
}
public function getInstagram(): ?string
{
return $this->instagram;
}
public function setInstagram(?string $instagram): self
{
$this->instagram = $instagram;
return $this;
}
public function getTiktok(): ?string
{
return $this->tiktok;
}
public function setTiktok(?string $tiktok): self
{
$this->tiktok = $tiktok;
return $this;
}
public function getFacebook(): ?string
{
return $this->facebook;
}
public function setFacebook(?string $facebook): self
{
$this->facebook = $facebook;
return $this;
}
public function getTwitch(): ?string
{
return $this->twitch;
}
public function setTwitch(?string $twitch): self
{
$this->twitch = $twitch;
return $this;
}
public function getImg(): ?string
{
return $this->img;
}
public function setImg(string $img): self
{
$this->img = $img;
return $this;
}
public function getPseudo(): ?string
{
return $this->pseudo;
}
public function setPseudo(string $pseudo): self
{
$this->pseudo = $pseudo;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getCreatedTime(): ?\DateTimeInterface
{
return $this->created_time;
}
public function setCreatedTime(\DateTimeInterface $created_time): self
{
$this->created_time = $created_time;
return $this;
}
public function getUpdatedTime(): ?\DateTimeInterface
{
return $this->updated_time;
}
public function setUpdatedTime(\DateTimeInterface $updated_time): self
{
$this->updated_time = $updated_time;
return $this;
}
/**
* #return Collection<int, Tag>
*/
public function getTags(): Collection
{
return $this->tags;
}
public function addTag(Tag $tag): self
{
if (!$this->tags->contains($tag)) {
$this->tags[] = $tag;
}
return $this;
}
public function removeTag(Tag $tag): self
{
$this->tags->removeElement($tag);
return $this;
}
/**
* #return Collection<int, Games>
*/
public function getGames(): Collection
{
return $this->games;
}
public function addGame(Games $game): self
{
if (!$this->games->contains($game)) {
$this->games[] = $game;
}
return $this;
}
public function removeGame(Games $game): self
{
$this->games->removeElement($game);
return $this;
}
public function getIsVerified(): ?bool
{
return $this->isVerified;
}
public function setIsVerified(bool $isVerified): self
{
$this->isVerified = $isVerified;
return $this;
}
}
And here my Tag entity :
<?php
namespace App\Entity;
use App\Repository\TagRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: TagRepository::class)]
class Tag
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $name;
#[ORM\Column(type: 'datetime')]
private $created_time;
#[ORM\Column(type: 'datetime')]
private $updated_time;
#[ORM\ManyToMany(targetEntity: User::class, mappedBy: 'tags',cascade: ['persist'])]
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
$this->created_time = new \DateTime();
$this->updated_time = new \DateTime();
}
public function __toString()
{
return $this->name;
}
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 getCreatedTime(): ?\DateTimeInterface
{
return $this->created_time;
}
public function setCreatedTime(\DateTimeInterface $created_time): self
{
$this->created_time = $created_time;
return $this;
}
public function getUpdatedTime(): ?\DateTimeInterface
{
return $this->updated_time;
}
public function setUpdatedTime(\DateTimeInterface $updated_time): self
{
$this->updated_time = $updated_time;
return $this;
}
/**
* #return Collection<int, User>
*/
public function getUsers(): Collection
{
return $this->users;
}
public function addUser(User $user): self
{
if (!$this->users->contains($user)) {
$this->users[] = $user;
$user->addTag($this);
}
return $this;
}
public function removeUser(User $user): self
{
if ($this->users->removeElement($user)) {
$user->removeTag($this);
}
return $this;
}
}
You can check if the tag exists before persisting it:
if ($formTag->isSubmitted() && $formTag->isValid()) {
$dataFormTag = $formTag->getData();
$userTagsAssocied = $user->getTags();
$userTagsAssociedArray = $userTagsAssocied->toArray();
if (in_array($dataFormTag->getName(), $userTagsAssociedArray)) {
$this->addFlash('danger', 'Vous avez deja le tag ' . $dataFormTag->getName() . ' associé à votre profil');
return $this->redirectToRoute('app_user_profil');
}
$existingTag = $tagRepository->findOneByName($dataFormTag->getName());
if ($existingTag !== null) {
$user->addTag($existingTag);
} else {
$user->addTag($dataFormTag);
}
$this->entityManager->persist($user);
$this->entityManager->flush();
$this->addFlash('success', 'Tag ' . $dataFormTag->getName() . ' bien lier à votre profil');
return $this->redirectToRoute('app_user_profil');
}
To prevent any duplicates because of case issue you could write your own findByName method in your repository
// TagRepository.php
public function findOneByName($name) {
return $this->createQueryBuilder('t')
->where('upper(t.name) = upper(:name)')
->setParameter('name', $name)
->getQuery()
->getOneOrNullResult();
}