Key "roles" for array with keys "0, 1, 2" does not exist [closed] - php

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 16 hours ago.
Improve this question
this is the entity file:
<?php
namespace App\Entity;
use App\Repository\UserRepository;
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;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 180, unique: true)]
#[Assert\Email(message:"the email '{{ value }}' is required")]
private ?string $email = null;
#[ORM\Column]
private array $roles = [];
/**
* #var string The hashed password
*/
#[ORM\Column]
private ?string $password = null;
#[ORM\Column(length: 255)]
public ?string $full_name = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
public ?\DateTimeInterface $date_naiss = null;
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;
}
/**
* #deprecated since Symfony 5.3, use getUserIdentifier instead
*/
public function getUsername(): 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;
}
/**
* Returning a salt is only needed, if you are not using a modern
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
*
* #see UserInterface
*/
public function getSalt(): ?string
{
return null;
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getFullName(): ?string
{
return $this->full_name;
}
public function setFullName(string $full_name): self
{
$this->full_name = $full_name;
return $this;
}
public function getDateNaiss(): ?\DateTimeInterface
{
return $this->date_naiss;
}
public function setDateNaiss(\DateTimeInterface $date_naiss): self
{
$this->date_naiss = $date_naiss;
return $this;
}
}
this is the twig file (i removed the template code because its too long to post):
{% extends 'back.html.twig' %}
{% block body %}
<tr>
<th>Id</th>
<th>Full Name</th>
<th>Email</th>
<th>Date of Birth</th>
<th></th>
<th>Action<th>
</tr>
{% for i in user %}
<tr>
<td>{{i.id}}</td>
<td>{{i.full_name}}</td>
<td>{{i.email}}</td>
<td>{{i.date_naiss | date('Y-m-d') }}</td>
<td>
{% for role in user.roles %}
{% if role == "ROLE_USER" %}
Utilisateur
{% elseif role == "ROLE_EDITOR" %}
Editeur
{% elseif role == "ROLE_ADMIN" %}
Administrateur
{% endif %}
{% endfor %}
</td>
<td>Delete
Update</td>
</tr>
{% endfor %}
{% endblock %}
and this is the list function i'm using in the controller:
#[Route('admin/list', name: 'user_list')]
public function userlist(UserRepository $user): Response
{
return $this->render('admin/list.html.twig', [
'user' => $user->findall()
]);
}
i'm using the predefined entity User in symfony 5 with the roles array, whenever i try to run the route "/admin/list" it shows the error above, even thought the roles array is defined in the entity file.

Related

Load an image in public repository symfony

Hi I would like to upload a picture associated to a restaurant entity. The image is stocked good in the restaurant entity but impossible to load it in the public folder to use it in my twig file with the assets. Do you have solutions ? May I am uploading bad the image
RestaurantController.php
<?php
namespace App\Controller;
use App\Entity\Image;
use App\Entity\Restaurant;
use App\Form\RestaurantType;
use App\Repository\RestaurantRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("/restaurant")
*/
class RestaurantController extends AbstractController
{
/**
* #Route("/index", name="app_restaurant_index", methods={"GET"})
*/
public function index(RestaurantRepository $restaurantRepository): Response
{
return $this->render('restaurant/index.html.twig', [
'restaurants' => $restaurantRepository->findAll(),
]);
}
/**
* #Route("/new", name="app_restaurant_new", methods={"GET", "POST"})
*/
public function new(Request $request, RestaurantRepository $restaurantRepository, EntityManagerInterface $entityManagerInterface): Response
{
$restaurant = new Restaurant();
$form = $this->createForm(RestaurantType::class, $restaurant);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//upload img
if ($form->get('image')->getData() != null) {
$image = $form->get('image')->getData();
$fichier = md5(uniqid()) . '.' . $image->guessExtension();
// On copie le fichier dans le dossier build
$image->move(
$this->getParameter('images_directory'), // Destination folder -> images_directory: '/public/build'
$fichier // File name
);
// On crée l'image dans la base de données
$img = new Image();
$img->setName($fichier);
$restaurant->setImage($img);
}
$restaurant->setUser($this->getUser());
$restaurantRepository->add($restaurant, true);
return $this->redirectToRoute('app_restaurant_show', ['id' => $restaurant->getId()], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('restaurant/new.html.twig', [
'restaurant' => $restaurant,
'form' => $form,
]);
}
/**
* #Route("/{id}", name="app_restaurant_show", methods={"GET"})
*/
public function show(Restaurant $restaurant): Response
{
// if ($restaurant->getImage() != null) {
// $image= $restaurant->getImage();
// $image->move(
// $this->getParameter('images_directory'),
// $fichier
// );
// }
return $this->render('restaurant/show.html.twig', [
'restaurant' => $restaurant,
]);
}
/**
* #Route("/{id}/edit", name="app_restaurant_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, Restaurant $restaurant, RestaurantRepository $restaurantRepository): Response
{
$form = $this->createForm(RestaurantType::class, $restaurant);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$restaurantRepository->add($restaurant, true);
return $this->redirectToRoute('app_restaurant_show', ['id' => $restaurant->getId()], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('restaurant/edit.html.twig', [
'restaurant' => $restaurant,
'form' => $form,
]);
}
/**
* #Route("/{id}", name="app_restaurant_delete", methods={"POST"})
*/
public function delete(Request $request, Restaurant $restaurant, RestaurantRepository $restaurantRepository): Response
{
if ($this->isCsrfTokenValid('delete' . $restaurant->getId(), $request->request->get('_token'))) {
$restaurantRepository->remove($restaurant, true);
}
return $this->redirectToRoute('app_restaurant_index', [], Response::HTTP_SEE_OTHER);
}
}
Image.php
<?php
namespace App\Entity;
use App\Repository\ImageRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ImageRepository::class)]
class Image
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\OneToOne(inversedBy: 'image', cascade: ['persist'])]
#[ORM\JoinColumn(name: "restaurant_id", nullable: true)]
private ?Restaurant $restaurant = null;
#[ORM\OneToOne(inversedBy: 'image', cascade: ['persist'])]
#[ORM\JoinColumn(name: "dish_id", nullable: true)]
private ?Dish $dish = 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 getRestaurant(): ?Restaurant
{
return $this->restaurant;
}
public function setRestaurant(?Restaurant $restaurant): self
{
$this->restaurant = $restaurant;
return $this;
}
public function getDish(): ?Dish
{
return $this->dish;
}
public function setDish(?Dish $dish): self
{
$this->dish = $dish;
return $this;
}
}
Restaurant.php
<?php
namespace App\Entity;
use App\Repository\RestaurantRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: RestaurantRepository::class)]
class Restaurant
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column(length: 255)]
private ?string $address = null;
#[ORM\Column(type: Types::DECIMAL, precision: 3, scale: 1, nullable: true)]
private ?string $ecoRate = null;
#[ORM\Column(type: Types::DECIMAL, precision: 3, scale: 1, nullable: true)]
private ?string $rate = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $info = null;
#[ORM\ManyToMany(targetEntity: Category::class, inversedBy: 'restaurants')]
private Collection $category;
// #[ORM\OneToMany(mappedBy: 'restaurant', targetEntity: Dish::class)]
// private Collection $dishes;
#[ORM\OneToMany(mappedBy: 'restaurant', targetEntity: Menu::class)]
private Collection $menus;
#[ORM\OneToMany(mappedBy: 'restaurant', targetEntity: Order::class)]
private Collection $orders;
#[ORM\ManyToMany(targetEntity: User::class, mappedBy: 'favorites')]
private Collection $users;
#[ORM\Column(length: 255)]
private ?string $siret = null;
#[ORM\Column(length: 255)]
private ?string $phoneNumber = null;
#[ORM\Column(length: 255)]
private ?string $email = null;
#[ORM\Column]
private ?bool $state = null;
#[ORM\OneToOne(inversedBy: 'restaurant', cascade: ['persist', 'remove'])]
private ?User $user = null;
#[ORM\OneToOne(mappedBy: 'restaurant', cascade: ['persist', 'remove'])]
private ?Image $image = null;
public function __construct()
{
$this->category = new ArrayCollection();
$this->menus = new ArrayCollection();
$this->orders = new ArrayCollection();
$this->users = new ArrayCollection();
}
public function __toString()
{
return (string) $this->getId();
}
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 getAddress(): ?string
{
return $this->address;
}
public function setAddress(string $address): self
{
$this->address = $address;
return $this;
}
public function getEcoRate(): ?string
{
return $this->ecoRate;
}
public function setEcoRate(?string $ecoRate): self
{
$this->ecoRate = $ecoRate;
return $this;
}
public function getRate(): ?string
{
return $this->rate;
}
public function setRate(?string $rate): self
{
$this->rate = $rate;
return $this;
}
public function getInfo(): ?string
{
return $this->info;
}
public function setInfo(?string $info): self
{
$this->info = $info;
return $this;
}
/**
* #return Collection<int, Category>
*/
public function getCategory(): Collection
{
return $this->category;
}
public function addCategory(Category $category): self
{
if (!$this->category->contains($category)) {
$this->category->add($category);
}
return $this;
}
public function removeCategory(Category $category): self
{
$this->category->removeElement($category);
return $this;
}
// /**
// * #return Collection<int, Dish>
// */
// public function getDishes(): Collection
// {
// return $this->dishes;
// }
// public function addDish(Dish $dish): self
// {
// if (!$this->dishes->contains($dish)) {
// $this->dishes->add($dish);
// $dish->setRestaurant($this);
// }
// return $this;
// }
// public function removeDish(Dish $dish): self
// {
// if ($this->dishes->removeElement($dish)) {
// // set the owning side to null (unless already changed)
// if ($dish->getRestaurant() === $this) {
// $dish->setRestaurant(null);
// }
// }
// return $this;
// }
/**
* #return Collection<int, Menu>
*/
public function getMenus(): Collection
{
return $this->menus;
}
public function addMenu(Menu $menu): self
{
if (!$this->menus->contains($menu)) {
$this->menus->add($menu);
$menu->setRestaurant($this);
}
return $this;
}
public function removeMenu(Menu $menu): self
{
if ($this->menus->removeElement($menu)) {
// set the owning side to null (unless already changed)
if ($menu->getRestaurant() === $this) {
$menu->setRestaurant(null);
}
}
return $this;
}
/**
* #return Collection<int, Order>
*/
public function getOrders(): Collection
{
return $this->orders;
}
public function addOrder(Order $order): self
{
if (!$this->orders->contains($order)) {
$this->orders->add($order);
$order->setRestaurant($this);
}
return $this;
}
public function removeOrder(Order $order): self
{
if ($this->orders->removeElement($order)) {
// set the owning side to null (unless already changed)
if ($order->getRestaurant() === $this) {
$order->setRestaurant(null);
}
}
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->add($user);
$user->addFavorite($this);
}
return $this;
}
public function removeUser(User $user): self
{
if ($this->users->removeElement($user)) {
$user->removeFavorite($this);
}
return $this;
}
public function getSiret(): ?string
{
return $this->siret;
}
public function setSiret(string $siret): self
{
$this->siret = $siret;
return $this;
}
public function getPhoneNumber(): ?string
{
return $this->phoneNumber;
}
public function setPhoneNumber(string $phoneNumber): self
{
$this->phoneNumber = $phoneNumber;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function isState(): ?bool
{
return $this->state;
}
public function setState(bool $state): self
{
$this->state = $state;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getImage(): ?Image
{
return $this->image;
}
public function setImage(?Image $image): self
{
// unset the owning side of the relation if necessary
if ($image === null && $this->image !== null) {
$this->image->setRestaurant(null);
}
// set the owning side of the relation if necessary
if ($image !== null && $image->getRestaurant() !== $this) {
$image->setRestaurant($this);
}
$this->image = $image;
return $this;
}
}
twig file
{% extends 'base.html.twig' %}
{% block title %}Restaurant
{% endblock %}
{% block body %}
<h1>Restaurant</h1>
<table class="table">
<tbody>
<tr>
<th>Id</th>
<td>{{ restaurant.id }}</td>
</tr>
<tr>
<th>Address</th>
<td>{{ restaurant.address }}</td>
</tr>
<tr>
<th>Email</th>
<td>{{ restaurant.email }}</td>
</tr>
<tr>
<th>Telephone</th>
<td>{{ restaurant.phoneNumber }}</td>
</tr>
<tr>
<th>Rate</th>
<td>{{ restaurant.rate }}</td>
</tr>
{% if restaurant.ecoRate %}
<tr>
<th>Eco rate</th>
<td>{{ restaurant.ecoRate }}</td>
</tr>
{% endif %}
<tr>
<th>Info</th>
<td>{{ restaurant.info }}</td>
</tr>
<tr>
<th>Siret</th>
<td>{{ restaurant.siret }}</td>
</tr>
{% if restaurant.image %}
<tr>
<th>Image</th>
<td><a href="{{ asset('build/images/' ~ restaurant.image.name) }}"></td>
{# <td><img src="{{ asset('build/images/' ~ restaurant.image.name) }}"></td> #}
</tr>
{% endif %}
<tr>
<th>Categorie</th>
{% for cat in restaurant.category %}
<td>{{ cat.name }}</td>
{% endfor %}
</tr>
</tbody>
</table>
{# back to list #}
edit
Menu
{# Produit #}
{# Catégorie #}
{{ include('restaurant/_delete_form.html.twig') }}
<pre>
{{ dump(restaurant) }}
{{ dump(restaurant.image.name) }}
</pre>
{% endblock %}
Did you check if your image is stored correctly? In the good folder?
(In your controller, it seems to be in « /public/build », but in the Twig you concatenate with « /public/build/images »

Symfony 6 data access and transmission between multiple tables with format error [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 12 months ago.
Improve this question
The project is a website written in symfony. The problem there is that
there is a user and a consultant which is a separate table, but a user
becomes the consultant, and when this consultant wants to give up his
free time and I want to store it in a third table that listens for
the interval name I have to fill in the consultant ID.
user_table:
<?php
namespace App\Entity;
use App\Repository\UserRepository;
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;
/**
* #UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
#[ORM\Entity(repositoryClass: UserRepository::class)]
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;
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;
}
}
cons table:
<?php
namespace App\Entity;
use App\Repository\ConsRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ConsRepository::class)]
class Cons
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\OneToOne(targetEntity: User::class, cascade: ['persist', 'remove'])]
private $user;
#[ORM\OneToMany(mappedBy: 'cons_id', targetEntity: Intervall::class)]
private $intervalls;
public function __construct()
{
$this->intervalls = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getUserId(): ?User
{
return $this->user;
}
public function setUserId(?User $user): self
{
$this->user = $user;
return $this;
}
/**
* #return Collection|Intervall[]
*/
public function getIntervalls(): Collection
{
return $this->intervalls;
}
public function addIntervall(Intervall $intervall): self
{
if (!$this->intervalls->contains($intervall)) {
$this->intervalls[] = $intervall;
$intervall->setConsId($this);
}
return $this;
}
public function removeIntervall(Intervall $intervall): self
{
if ($this->intervalls->removeElement($intervall)) {
// set the owning side to null (unless already changed)
if ($intervall->getConsId() === $this) {
$intervall->setConsId(null);
}
}
return $this;
}
}
intervall table:
<?php
namespace App\Entity;
use App\Repository\IntervallRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: IntervallRepository::class)]
class Intervall
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'datetime')]
private $start;
#[ORM\Column(type: 'datetime')]
private $end;
#[ORM\Column(type: 'boolean')]
private $more;
#[ORM\Column(type: 'time')]
private $cons_time;
#[ORM\Column(type: 'time')]
private $free_time;
#[ORM\ManyToOne(targetEntity: Cons::class, inversedBy: 'intervalls')]
private $cons;
public function __construct()
{
$this->cons = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getStart(): ?\DateTimeInterface
{
return $this->start;
}
public function setStart(\DateTimeInterface $start): self
{
$this->start = $start;
return $this;
}
public function getEnd(): ?\DateTimeInterface
{
return $this->end;
}
public function setEnd(\DateTimeInterface $end): self
{
$this->end = $end;
return $this;
}
public function getMore(): ?bool
{
return $this->more;
}
public function setMore(bool $more): self
{
$this->more = $more;
return $this;
}
public function getConsTime(): ?\DateTimeInterface
{
return $this->cons_time;
}
public function setConsTime(\DateTimeInterface $cons_time): self
{
$this->cons_time = $cons_time;
return $this;
}
public function getFreeTime(): ?\DateTimeInterface
{
return $this->free_time;
}
public function setFreeTime(\DateTimeInterface $free_time): self
{
$this->free_time = $free_time;
return $this;
}
public function getConsId(): ?Cons
{
return $this->cons;
}
public function setConsId(?Cons $cons): self
{
$this->cons = $cons;
return $this;
}
}
intervall wrong code slise:
#[Route('/new', name: 'intervall_new', methods: ['GET', 'POST'])]
public function new(Request $request, EntityManagerInterface $entityManager): Response
{
$user_id = $this->getUser()->getId();
$cnsuseridrepo = $entityManager->getRepository(Cons::class);
$cnsuserid = $cnsuseridrepo->findOneBy(["user"=>$user_id]);
$intervall = new Intervall();
$intervall->setConsId(($cnsuserid->getId());
$form = $this->createForm(IntervallType::class, $intervall);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($intervall);
$entityManager->flush();
return $this->redirectToRoute('intervall_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('intervall/new.html.twig', [
'intervall' => $intervall,
'form' => $form,
]);
}
that would be the mistake I see:
Seems like setter method allows only object of Cons or null value, so you have to set it as object.
$intervall = new Intervall();
$intervall->setConsId($cnsuserid);
$form = $this->createForm(IntervallType::class, $intervall);
$form->handleRequest($request);

Entity not found with Symfony 5.1

I have an issue with an Entity.
The goal is to display a Form which the user can use to change his personal information like the Email or password. I created a form for that, but when I created the /Edit Route I get the following error:
"App\Entity\Users object not found by the #ParamConverter annotation."
Here's my Controller:
<?php
namespace App\Controller;
use App\Entity\Users;
use App\Form\EditProfileType;
use App\Form\UsersType;
use App\Repository\UsersRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("/users")
*/
class UsersController extends AbstractController
{
/**
* #Route("/", name="users_index", methods={"GET"})
*/
public function index(): Response
{
return $this->render('users/index.html.twig');
}
/**
* #Route("/{id}", name="users_show", methods={"GET"})
*/
public function show(Users $user): Response
{
return $this->render('users/show.html.twig', [
'user' => $user,
]);
}
/**
* #Route("/edit", name="users_edit")
*/
public function editProfile(Request $request): Response
{
$user = $this->getUser();
$form = $this->createForm(EditProfileType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
$this->addflash('message', 'Profile mis à jour');
return $this->redirectToRoute('users');
}
return $this->render('users/editprofile.html.twig', [
'form' => $form->createView(),
]);
}
Here's the form:
<?php
namespace App\Form;
use App\Entity\Users;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class EditProfileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email')
->add('pseudo', TextType::class)
->add('Valider', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Users::class,
]);
}
}
Here's the Entity Users:
<?php
namespace App\Entity;
use App\Repository\UsersRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\Entity(repositoryClass=UsersRepository::class)
* #UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
class Users implements UserInterface
{
/**
* #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 = [];
/**
* #var string The hashed password
* #ORM\Column(type="string")
*/
private $password;
/**
* #ORM\OneToMany(targetEntity=Commentaires::class, mappedBy="auteur", orphanRemoval=true)
*/
private $commentaires;
/**
* #ORM\OneToMany(targetEntity=Notes::class, mappedBy="user", orphanRemoval=true)
*/
private $note;
/**
* #ORM\Column(type="string", length=100)
*/
private $pseudo;
public function __construct()
{
$this->commentaires = new ArrayCollection();
$this->note = new ArrayCollection();
}
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 getUsername(): 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 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;
}
/**
* #return Collection|Commentaires[]
*/
public function getCommentaires(): Collection
{
return $this->commentaires;
}
public function addCommentaire(Commentaires $commentaire): self
{
if (!$this->commentaires->contains($commentaire)) {
$this->commentaires[] = $commentaire;
$commentaire->setAuteur($this);
}
return $this;
}
public function removeCommentaire(Commentaires $commentaire): self
{
if ($this->commentaires->contains($commentaire)) {
$this->commentaires->removeElement($commentaire);
// set the owning side to null (unless already changed)
if ($commentaire->getAuteur() === $this) {
$commentaire->setAuteur(null);
}
}
return $this;
}
/**
* #return Collection|Notes[]
*/
public function getNote(): Collection
{
return $this->note;
}
public function addNote(Notes $note): self
{
if (!$this->note->contains($note)) {
$this->note[] = $note;
$note->setUser($this);
}
return $this;
}
public function removeNote(Notes $note): self
{
if ($this->note->contains($note)) {
$this->note->removeElement($note);
// set the owning side to null (unless already changed)
if ($note->getUser() === $this) {
$note->setUser(null);
}
}
return $this;
}
public function getPseudo(): ?string
{
return $this->pseudo;
}
public function setPseudo(string $pseudo): self
{
$this->pseudo = $pseudo;
return $this;
}
}
Here's the View Editprofile.html.twig:
{% extends 'basefront.html.twig' %}
{% block title %} Profile de {{ app.user.pseudo }} {% endblock %}
{% block body %}
<h1 class="h1 text-center">Modification du profile de {{ app.user.pseudo }}</h1>
{{ form(form) }}
{% endblock %}
order matters. especially when routing without requirements. you have the following routes (update: added prefix, thanks #Cerad!):
/users/ users_index
/users/{id} users_show
/users/edit users_edit
now, when you request the uri /users/edit the UrlMatcher will iterate over your routes to see if and which matches, stopping on the first match.
/users/ obviously doesn't match
/users/{id} does match, since {id} is allowed to be any alpha-numeric string (+ few extra chars), and edit matches that, leading to the users_show route, on which the User object cannot be determined by the id "edit`. And thus, the error message appears. One way to fix this would be to add requirements to the route matching - assuming the id is numerical only:
/**
* #Route("/{id}", ..., requirements={"id":"\d+"})
*/
I also agree with #Cerad that Users is a very bad name for an entity. They're usually in singular form.

Populate dependent select box using Symfony & Ajax

I was not able to find any solution matching my case scenario, so I decided to ask here:
Basically what I need to achieve is to render a form with several select boxes namely the Company, ProductsCategory, and Products. So depending on which category the user chooses, I want to filter and show only the products of that chosen category. I tried to follow the Symfony documentation as mentioned here , but I cannot get it to work. the front-end products select box remains blank even after a category has been set and also the ajax return with status 500 with error:
Return value of App\Entity\ProductsCategory::getProducts() must be an instance of App\Entity\Products or null, instance of Doctrine\ORM\PersistentCollection returned
here are the codes:
My Exportables entity
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\ExportablesRepository")
*/
class Exportables
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\ExportCompany", inversedBy="exportables")
* #ORM\JoinColumn(nullable=false)
*/
private $company;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Products", inversedBy="exportables")
* #ORM\JoinColumn(nullable=false)
*/
private $product;
/**
* #ORM\Column(type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\ProductsCategory")
* #ORM\JoinColumn(nullable=false)
*/
private $category;
public function getId(): ?int
{
return $this->id;
}
public function getCompany(): ?ExportCompany
{
return $this->company;
}
public function setCompany(?ExportCompany $company): self
{
$this->company = $company;
return $this;
}
public function getProduct(): ?Products
{
return $this->product;
}
public function setProduct(?Products $product): self
{
$this->product = $product;
return $this;
}
public function getIsActive(): ?bool
{
return $this->isActive;
}
public function setIsActive(bool $isActive): self
{
$this->isActive = $isActive;
return $this;
}
public function getCategory(): ?ProductsCategory
{
return $this->category;
}
public function setCategory(?ProductsCategory $category): self
{
$this->category = $category;
return $this;
}
}
ProductsCategory entity:
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\ProductsCategoryRepository")
*/
class ProductsCategory
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=50)
*/
private $categoryTitle;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $categoryDescription;
/**
* #ORM\Column(type="boolean")
*/
private $isActive;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Products", mappedBy="category", cascade={"persist", "remove"})
*/
private $products;
public function __construct()
{
$this->product = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getCategoryTitle(): ?string
{
return $this->categoryTitle;
}
public function setCategoryTitle(string $categoryTitle): self
{
$this->categoryTitle = $categoryTitle;
return $this;
}
public function getCategoryDescription(): ?string
{
return $this->categoryDescription;
}
public function setCategoryDescription(?string $categoryDescription): self
{
$this->categoryDescription = $categoryDescription;
return $this;
}
public function getIsActive(): ?bool
{
return $this->isActive;
}
public function setIsActive(bool $isActive): self
{
$this->isActive = $isActive;
return $this;
}
public function getProducts(): ?Products
{
return $this->products;
}
public function setProducts(Products $products): self
{
$this->products = $products;
// set the owning side of the relation if necessary
if ($products->getCategory() !== $this) {
$products->setCategory($this);
}
return $this;
}
public function __toString()
{
return $this->categoryTitle;
}
}
Products entity:
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\ProductsRepository")
*/
class Products
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=50)
*/
private $productTitle;
/**
* #ORM\Column(type="text")
*/
private $productDescription;
/**
* #ORM\Column(type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\ProductsCategory", inversedBy="products", cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=false)
*/
private $category;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Exportables", mappedBy="product")
*/
private $exportables;
public function __construct()
{
$this->exportables = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getProductTitle(): ?string
{
return $this->productTitle;
}
public function setProductTitle(string $productTitle): self
{
$this->productTitle = $productTitle;
return $this;
}
public function getProductDescription(): ?string
{
return $this->productDescription;
}
public function setProductDescription(string $productDescription): self
{
$this->productDescription = $productDescription;
return $this;
}
public function getIsActive(): ?bool
{
return $this->isActive;
}
public function setIsActive(bool $isActive): self
{
$this->isActive = $isActive;
return $this;
}
public function getCategory(): ?ProductsCategory
{
return $this->category;
}
public function setCategory(ProductsCategory $category): self
{
$this->category = $category;
return $this;
}
/**
* #return Collection|Exportables[]
*/
public function getExportables(): Collection
{
return $this->exportables;
}
public function addExportable(Exportables $exportable): self
{
if (!$this->exportables->contains($exportable)) {
$this->exportables[] = $exportable;
$exportable->setProduct($this);
}
return $this;
}
public function removeExportable(Exportables $exportable): self
{
if ($this->exportables->contains($exportable)) {
$this->exportables->removeElement($exportable);
// set the owning side to null (unless already changed)
if ($exportable->getProduct() === $this) {
$exportable->setProduct(null);
}
}
return $this;
}
public function __toString(){
return $this->productTitle;
}
}
Exportables Type:
namespace App\Form;
use App\Entity\Products;
use App\Entity\Exportables;
use App\Entity\ProductsCategory;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class ExportablesType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('company')
->add('category', EntityType::class, array(
'class' => ProductsCategory::class,
'placeholder' => 'Select a Category...',
))
->add('isActive')
;
$formModifier = function (FormInterface $form, ProductsCategory $cat = null) {
$products = null === $cat ? [] : $cat->getProducts();
dump($products);
$form->add('product', EntityType::class, [
'class' => 'App\Entity\Products',
'placeholder' => '',
'choices' => $products,
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. SportMeetup
$data = $event->getData();
$formModifier($event->getForm(), $data->getCategory());
}
);
$builder->get('category')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$cat = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $cat);
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Exportables::class,
]);
}
}
ExportablesController:
namespace App\Controller;
use App\Entity\Exportables;
use App\Form\ExportablesType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class ExportablesController extends AbstractController
{
/**
* #Route("/admin-panel/exportables/new", name="exportables_create")
* #Route("/admin-panel/exportables/{id}/edit", name="exportables_edit")
*/
public function exportables_create_and_edit(Request $request, EntityManagerInterface $em, Exportables $exportables = null)
{
if(!$exportables){
$exportables = new Exportables();
}
$form = $this->createForm(ExportablesType::class, $exportables);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$em->persist($exportables);
$em->flush();
}
return $this->render('/admin-panel/exportables_create.html.twig', [
'exForm' => $form->createView(),
'editMode' => $exportables->getId() !== null
]);
}
}
Finally, the twig file rendering the form:
{% extends '/admin-panel/base-admin.html.twig' %}
{% block body %}
{{ form_start(exForm) }}
<div class="form-group">
{{ form_row(exForm.company, {'attr':{'class':"form-control"}}) }}
</div>
<div class="form-group">
{{ form_row(exForm.category, {'attr':{'class':"form-control"}}) }}
</div>
{% if exForm.product is defined %}
<div class="form-group">
{{ form_row(exForm.product, {'label': "Product..", 'attr':{'class':"form-control"}}) }}
</div>
{% endif %}
<div class="form-group">
<div class="custom-control custom-checkbox">
{{ form_widget(exForm.isActive, {'attr': {'class': "custom-control-input", 'checked': "checked"}}) }}
<label class="custom-control-label" for="exportables_isActive">Visible on the website?</label>
</div>
</div>
<button type="submit" class="btn btn-success">Create</button>
{{ form_end(exForm) }}
{% endblock %}
{% block javascripts %}
<script>
{# //for some reasons this line doesnt work $(document).ready(function() { #}
jQuery(document).ready(function($){
var $cat = $('#exportables_category');
// When cat gets selected ...
$cat.change(function() {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
// Simulate form data, but only include the selected cat value.
var data = {};
data[$cat.attr('name')] = $cat.val();
console.log("cat val " + $cat.val());
//console.log($form.attr('method'));
const url = "{{ path('exportables_create')|escape('js') }}";
//console.log(data);
//console.log(url);
//why undefined?? console.log($form.attr('action'));
// Submit data via AJAX to the form's action path.
$.ajax({
//url : $form.attr('action'),
url : url,
type: $form.attr('method'),
data : data,
success: function(html) {
// Replace current position field ...
$('#exportables_product').replaceWith(
// ... with the returned one from the AJAX response.
//$(html).find('#exportables_product')
array(1,2,3)
);
// Position field now displays the appropriate positions.
}
});
});
});
</script>
{% endblock %}
Any help is greatly appreciated.
I didn't take the time to analyse all your code, so I'm not sure it will solve the whole problem, but it may help.
I guess there is something weird inside the ProductsCategory entity class. Indeed the products property is annotated as a OneToMany relation:
/**
* #ORM\OneToMany(targetEntity="App\Entity\Products", mappedBy="category", cascade={"persist", "remove"})
*/
private $products;
This implies that this property refers to a collection (one category can have many products). But the getters/setters for this property are defined later as if it was a OneToOne relation:
public function getProducts(): ?Products
{
return $this->products;
}
public function setProducts(Products $products): self
{
$this->products = $products;
// set the owning side of the relation if necessary
if ($products->getCategory() !== $this) {
$products->setCategory($this);
}
return $this;
}
It looks like you modified the annotation without modifying the getters/setters, which typically should offer the following methods for a OneToMany relation:
public function getProducts(): Collection;
public function addProducts(Product $product): self;
public function removeProducts(Product $product): self;
A last point: you should rename your entity Products to Product, it will greatly improve the readability of your code: indeed, the entity Products actually represent only one product, not several ones.

Symfony - Key "skills" for array with keys "0, 1" does not exist

i'm trying to display all related properties of my Jointure Entity in twig.
Here are my 3 entities :
/**
* #ORM\Entity(repositoryClass="App\Repository\JointureRepository")
*/
class Jointure
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Skill", mappedBy="jointure")
*/
private $skills;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Answer", mappedBy="jointure")
*/
private $answers;
public function __construct()
{
$this->skills = new ArrayCollection();
$this->answers = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* #return Collection|Skill[]
*/
public function getSkills(): Collection
{
return $this->skills;
}
public function addSkill(Skill $skill): self
{
if (!$this->skills->contains($skill)) {
$this->skills[] = $skill;
$skill->setJointure($this);
}
return $this;
}
public function removeSkill(Skill $skill): self
{
if ($this->skills->contains($skill)) {
$this->skills->removeElement($skill);
// set the owning side to null (unless already changed)
if ($skill->getJointure() === $this) {
$skill->setJointure(null);
}
}
return $this;
}
/**
* #return Collection|Answer[]
*/
public function getAnswers(): Collection
{
return $this->answers;
}
public function addAnswer(Answer $answer): self
{
if (!$this->answers->contains($answer)) {
$this->answers[] = $answer;
$answer->setJointure($this);
}
return $this;
}
public function removeAnswer(Answer $answer): self
{
if ($this->answers->contains($answer)) {
$this->answers->removeElement($answer);
// set the owning side to null (unless already changed)
if ($answer->getJointure() === $this) {
$answer->setJointure(null);
}
}
return $this;
}
}
Skill entity with ManyToOne => Jointure relation :
/**
* #ORM\Entity(repositoryClass="App\Repository\SkillRepository")
*/
class Skill
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $label;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Jointure", inversedBy="skills")
* #ORM\JoinColumn(nullable=false)
*/
private $jointure;
public function getId(): ?int
{
return $this->id;
}
public function getLabel(): ?string
{
return $this->label;
}
public function setLabel(string $label): self
{
$this->label = $label;
return $this;
}
public function getJointure(): ?Jointure
{
return $this->jointure;
}
public function setJointure(?Jointure $jointure): self
{
$this->jointure = $jointure;
return $this;
}
}
My entity Answer is the same that Skill with UserEmail property.
So in my controller :
class HomeController extends AbstractController
{
/**
* #var JointureRepository
*/
public function __construct(JointureRepository $repository, ObjectManager $em)
{
$this->repository = $repository;
$this->em = $em;
}
/**
* #Route("/", name="home")
*/
public function index()
{
$JointureRepository = $this->getDoctrine()->getRepository(Jointure::class);
$jointure = $JointureRepository->findAll();
foreach($jointure as $jointures){
$skills = $jointures->getSkills();
$answers = $jointures->getAnswers();
}
$this->em->flush();
return $this->render('pages/home.html.twig', [
'controller_name' => 'HomeController',
'jointure' => $jointure,
'skills' => $skills,
'answers' => $answers,
]);
}
}
When i'm trying to display them in twig :
{% for jointures in jointure.skills %}
{{jointures.label}}
{% endfor %}
I've the following error : Key "skills" for array with keys "0, 1" does not exist.
At line : {% for jointures in jointure.skills %}
If i do :
{% for skill in skills %}
{{skill.id}}
{% endfor %}
3,4 appears but not the 1,2 related to Jointure with id = 0 ..
Could you help me please ?
Did you dump out the output of this line?
$jointure = $JointureRepository->findAll();
If you did, you should have seen that $jointure is not a single object of that class but an array.
You even used it as an array in your Controller code:
foreach($jointure as $jointures){
$skills = $jointures->getSkills();
$answers = $jointures->getAnswers();
}
You're using the array as it would be a single object in twig, that's your issue. You need to either go trough the array, to get the skills, or you need to receive a single jointure to use it as you'd like to.
{% for object in jointure %}
{% for jointures in object.skills %}
{{jointures.label}}
{% endfor %}
{% endfor %}
As a basic note, take a look at your naming of variables. Those are misleading and are not representing the value that it contains.
$arrJointures = $JointureRepository->findAll();
$arrJointures would be a suitable variable, since this contains an array of jointures. Also, with this naming, you should see that this code couln't be working.
{% for jointures in arrJointures.skills %}
{{jointures.label}}
{% endfor %}

Categories