I've got a 3 entities and I would like to get property from entity 1 to entity 3. Let me explain with my classes :
class City
{
#[ORM\Column(type: 'string', length: 255)]
#[Assert\NotBlank]
#[Assert\Length(min: 1)]
private string $name;
#[ORM\Column(type: 'string', length: 20)]
#[Assert\NotBlank]
private string $code;
#[ORM\OneToOne(targetEntity: CityHomePage::class, cascade: ['persist', 'remove'])]
private CityHomePage $homePage;
public function getHomePage(): CityHomePage
{
return $this->homePage;
}
public function setHomePage(CityHomePage $homePage): self
{
$this->homePage = $homePage;
return $this;
}
}
class CityHomePage
{
#[ORM\OneToOne(targetEntity: City::class, cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(nullable: false)]
private City $city;
#[ORM\ManyToOne(targetEntity: Page::class, inversedBy: 'cityHomePages')]
#[ORM\JoinColumn(nullable: false)]
private Page $page;
#[ORM\OneToOne(targetEntity: Image::class, cascade: ['persist', 'remove'])]
private Image $image;
public function getCity(): ?City
{
return $this->city;
}
public function setCity(City $city): self
{
$this->city = $city;
return $this;
}
public function getPage(): ?Page
{
return $this->page;
}
public function setPage(?Page $page): self
{
$this->page = $page;
return $this;
}
public function getImage(): Image
{
return $this->image;
}
public function setImage(Image $image): self
{
$this->image = $image;
return $this;
}
}
class Page
{
#[ORM\Column(type: 'string', length: 100)]
#[Assert\Length(min: 1)]
private string $title;
/** #var Collection<int, CityHomePage> */
#[ORM\OneToMany(mappedBy: 'page', targetEntity: CityHomePage::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
private Collection $cityHomePages;
public function __construct()
{
parent::__construct();
$this->cityHomePages = new ArrayCollection();
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
/**
* #return Collection<int, CityHomePage>
*/
public function getCityHomePages(): Collection
{
return $this->cityHomePages;
}
public function addCityHomePage(CityHomePage $cityHomePage): self
{
if (!$this->cityHomePage->contains($cityHomePage)) {
$this->cityHomePage[] = $cityHomePage;
$cityHomePage->setPage($this);
}
return $this;
}
public function removeCityHomePage(CityHomePage $cityHomePage): self
{
if ($this->cityHomePage->removeElement($cityHomePage) && $cityHomePage->getPage() === $this) {
$cityHomePage->setPage(null);
}
return $this;
}
}
I created a CityCrudController and in my configurationField I add :
public function configureFields(string $pageName): iterable
{
return [
TextField::new('name',$this->translator->trans('EA.name'))->onlyOnIndex(),
TextField::new('code')->onlyOnIndex(),
AssociationField::new('homePage', $this->translator->trans('EA.image'))->onlyWhenUpdating(),
];
}
This is work but now I need to access from my CityCrudController the property 'title' from the Entity Page.
Is it a way to cross multiple entity to get what I need ?
Ok I found it => 'city.page.title'
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();
I'm new on Symfony 6 and i've got problem with 2 of my entities.
App\Entity\Mission :
The mappings App\Entity\Mission#idtagmissionassign and App\Entity\Tag#missionstag are inconsistent with each other.
App\Entity\Tag :
The association App\Entity\Tag#missionstag refers to the inverse side field App\Entity\Mission#tags which does not exist.
This is the relation betewen the 2 entities :
DB
This is Mission entity
<?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)]
#[ORM\Table(name: 'mission')]
class Mission
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $titlemission = null;
#[ORM\Column(length: 255)]
private ?string $descriptionmission = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $onsetdate = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $deadline = null;
#[ORM\Column]
private ?int $budgetmission = null;
/*#[ORM\Column(length: 255)]
private ?string $codeapemission = null;*/
#[ORM\Column(length: 255)]
private ?string $prioritymission = null;
#[ORM\ManyToMany(targetEntity: Tag::class, inversedBy: 'missionstag',cascade: ['persist'])]
#[ORM\JoinTable(name:'mission_tag')]
private Collection $idtagmissionassign;
#[ORM\ManyToOne(inversedBy: 'missions')]
#[ORM\JoinColumn(nullable: false)]
private ?User $iduser = null;
#[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'missionsassign')]
private Collection $idmissionassign;
#[ORM\Column(length: 100)]
private ?string $remote = null;
public function __construct()
{
$this->idtagmissionassign = new ArrayCollection();
$this->idmissionassign = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getTitlemission(): ?string
{
return $this->titlemission;
}
public function setTitlemission(string $titlemission): self
{
$this->titlemission = $titlemission;
return $this;
}
public function getDescriptionmission(): ?string
{
return $this->descriptionmission;
}
public function setDescriptionmission(string $descriptionmission): self
{
$this->descriptionmission = $descriptionmission;
return $this;
}
public function getOnsetdate(): ?\DateTimeInterface
{
return $this->onsetdate;
}
public function setOnsetdate(\DateTimeInterface $onsetdate): self
{
$this->onsetdate = $onsetdate;
return $this;
}
public function getDeadline(): ?\DateTimeInterface
{
return $this->deadline;
}
public function setDeadline(\DateTimeInterface $deadline): self
{
$this->deadline = $deadline;
return $this;
}
public function getBudgetmission(): ?int
{
return $this->budgetmission;
}
public function setBudgetmission(int $budgetmission): self
{
$this->budgetmission = $budgetmission;
return $this;
}
/*public function getCodeapemission(): ?string
{
return $this->codeapemission;
}
public function setCodeapemission(string $codeapemission): self
{
$this->codeapemission = $codeapemission;
return $this;
}*/
public function getPrioritymission(): ?string
{
return $this->prioritymission;
}
public function setPrioritymission(string $prioritymission): self
{
$this->prioritymission = $prioritymission;
return $this;
}
/**
* #return Collection<int, tag>
*/
public function getIdtagmissionassign(): Collection
{
return $this->idtagmissionassign;
}
public function addIdtagmissionassign(tag $idtagmissionassign): self
{
if (!$this->idtagmissionassign->contains($idtagmissionassign)) {
$this->idtagmissionassign->add($idtagmissionassign);
}
return $this;
}
public function removeIdtagmissionassign(tag $idtagmissionassign): self
{
$this->idtagmissionassign->removeElement($idtagmissionassign);
return $this;
}
public function getIduser(): ?user
{
return $this->iduser;
}
public function setIduser(?user $iduser): self
{
$this->iduser = $iduser;
return $this;
}
/**
* #return Collection<int, user>
*/
public function getIdmissionassign(): Collection
{
return $this->idmissionassign;
}
public function addIdmissionassign(user $idmissionassign): self
{
if (!$this->idmissionassign->contains($idmissionassign)) {
$this->idmissionassign->add($idmissionassign);
}
return $this;
}
public function removeIdmissionassign(user $idmissionassign): self
{
$this->idmissionassign->removeElement($idmissionassign);
return $this;
}
public function getRemote(): ?string
{
return $this->remote;
}
public function setRemote(string $remote): self
{
$this->remote = $remote;
return $this;
}
public function __toString(){
return $this->titlemission;
}
}
This is 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;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: TagRepository::class)]
class Tag
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 100)]
#[Assert\NotBlank]
#[Assert\Length(min:2)]
#[Assert\Valid]
private ?string $nomtag = null;
#[ORM\ManyToMany(targetEntity: Mission::class, mappedBy: 'tags')]
#[ORM\JoinTable(name:'mission_tag')]
private Collection $missionstag;
public function __construct()
{
$this->missionstag = new ArrayCollection();
}
// #[ORM\ManyToMany(targetEntity: Mission::class, inversedBy:"$idtagmissionassign")]
// private $genusScientists;
public function getId(): ?int
{
return $this->id;
}
public function getNomtag(): ?string
{
return $this->nomtag;
}
public function setNomtag(string $nomtag): self
{
$this->nomtag = $nomtag;
return $this;
}
/**
* #return Collection<int, Mission>
*/
public function getMissions(): Collection
{
return $this->missionstag;
}
public function addMission(Mission $mission): self
{
if (!$this->missionstag->contains($mission)) {
$this->missionstag->add($mission);
$mission->addTag($this);
}
return $this;
}
public function removeMission(Mission $mission): self
{
if ($this->missionstag->removeElement($mission)) {
$mission->removeTag($this);
}
return $this;
}
public function __toString(): string
{
return $this->nomtag;
}
}
Do you have an idea to help me to solve this problem ?
Many thanks
Change the mappedby and inversedby with no effect.
Trying some stuff follow internet guideline with no success.
Tag's property missionstag claims, that it is mapped by Missions's property "tags", but there is no such property, instead you have idtagmissionassign. (Side note: Your property names are bad, because they look like database columns, but you're using an ORM.
The first question you would have to ask yourself: will you need additional columns on your many-to-many table. If the answer is yes, ORM\ManyToMany isn't even the right fit. If the answer is no, it fits.
The case where it fits:
Mission should have the following property + attributes:
#[ORM\ManyToMany(targetEntity: Tag::class, inversedBy: 'missions', cascade: ['persist'])]
#[ORM\JoinTable(name: 'mission_tag')]
private Collection $tags;
and the Tag should have the following property + attributes:
#[ORM\ManyToMany(targetEntity: Mission::class, mappedBy: 'tags', cascade: ['persist'])]
#[ORM\JoinTable(name: 'mission_tag')] // <- is this the actual table name?
private Collection $missions;
the mappedBy and inversedBy must match the property name on the other entity, respectively.
If your mission_tag table doesn't have columns mission_id and tag_id, you might have to explicitly name the columns via the JoinColumn and InverseJoinColumn Attibutes.
For the case, where it doesn't fit, you would have to have an actual entity MissionTags with OneToMany on Mission/Tag that both reference it, and reversed ManyToOnes on MissionTags. But that wasn't what you asked.
BC\InventoryBundle\Entity\ProductRecipe:
type: entity
table: ProductRecipe
repositoryClass: BC\InventoryBundle\Entity\ProductRecipeRepository
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
amount: // Previously "ammount"
type: decimal
presision: 10
scale: 2
manyToOne:
products:
targetEntity: Product
// "Products" is named correctly but recipe is singular
// so for the sake of uniformity
inversedBy: recipes
joinColumn:
name: product_id
referencedColumnName: id
recipes:
targetEntity: Recipe
// Previously "Recipes", incorrect entity name
inversedBy: products
joinColumn:
name: recipe_id
referencedColumnName: id
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();
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 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();
}