Symfony4 setter where getter match id route? - php

I'm kindly new on Symfony
I'm doing a vote system but i guess this should work for like,
At the moment my controller function is this, this only create a new row with 1vote, but not update any $id created before.
/**
* #Route("/public/{id}/vote", name="poll_vote", methods="GET|POST")
*/
public function vote(Request $request, Poll $poll): Response
{
$inc = 1;
$em = $this->getDoctrine()->getManager();
$entity = new Poll();
$entity->setVotes($inc++);
$em->persist($entity);
$em->flush();
}
return $this->redirectToRoute('poll_public');
}
This is my button from twig template
<a href="{{ path('poll_vote', {'id': poll.id}) }}">
An this is my entity
class Poll
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $votes;
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 getVotes(): ?int
{
return $this->votes;
}
public function setVotes(?int $votes): self
{
$this->votes = $votes;
return $this;
}
}
I have no idea about how can match my getID from my entity and match for the $id from the #Route.
Any guide or suggestion would be really appreciate.
Thanks
EDIT:
Updated with the correct function after Arne answer:
/**
* #Route("/public/{id}", name="poll_vote", methods="GET|POST")
*/
public function vote($id)
{
$entityManager = $this->getDoctrine()->getManager();
$poll = $entityManager->getRepository(Poll::class)->find($id);
if (!$poll) {
throw $this->createNotFoundException(
'No polls found for id '.$id
);
}
$poll->setVotes($poll->getVotes()+1);
$entityManager->flush();
return $this->redirectToRoute('poll_public', [
'id' => $poll->getId()
]);
}

basically you have to get the ID from your request, query the Entitty Repository for your Poll Entity, update the votes and persist it back to your database.
Get the ID from your request
$id = $request->query->get('id');
Query the repository:
$entityManager = $this->getDoctrine()->getManager();
$poll= $entityManager->getRepository(Poll::class)->find($id);
Update the votes:
$poll->setVotes($poll->getVotes()+1);
Persist to the DB:
$entityManager->persist($poll);
$entityManager->flush();
Alternatively you could also use the ParamConverter to let Symfony get the Poll object for you. More information about updating objects can be found in the Doctrine Guide.
Note that yor route will only match existing polls, since id is a required parameter in the URL. You might add another route without an ID which is being used for creating new Poll entities.

Related

DQL request in SYmfony having two relations and returning an empty array

Hello there have something i dont understand about SQL i guess. I linked below the code and the image about my db shema for help you to understand.
So my problem with this request is that it return an empty array and i dont understand why its not working as from my understanding it should return an array containing all the "r.messages" that have the specified ID related to the fields relation. What do i do wrong ?
PS: for some context helping your understanding, im trying to build a messagery system from a user to another. The SQL request i try to do should return the conversation between two users.
public function listOfMessages($value, $value2)
{
return $this->createQueryBuilder('user')
->select('r.message')
->innerJoin('user.sender', 's')
->innerJoin('user.receiver', 'r')
->where('s.sender = :value')
->andWhere('r.recipient = :value2')
->setParameter(':value', $value)
->setParameter(':value2', $value2)
->getQuery()
->getResult()
;
}
DB shema
Entity User
use App\Repository\PrivateMessageRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=PrivateMessageRepository::class)
*/
class PrivateMessage
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $message;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="sender")
*/
private $sender;
/**
* #ORM\ManyToOne(targetEntity=user::class, inversedBy="receiver")
*/
private $recipient;
/**
* #ORM\Column(type="boolean", nullable=true)
*/
private $isRead = 0;
/**
* #ORM\Column(type="datetime_immutable", nullable=true)
*/
private $sentAt;
public function getId(): ?int
{
return $this->id;
}
public function getMessage(): ?string
{
return $this->message;
}
public function setMessage(?string $message): self
{
$this->message = $message;
return $this;
}
public function getSender(): ?User
{
return $this->sender;
}
public function setSender(?User $sender): self
{
$this->sender = $sender;
return $this;
}
public function getRecipient(): ?user
{
return $this->recipient;
}
public function setRecipient(?user $recipient): self
{
$this->recipient = $recipient;
return $this;
}
public function getIsRead(): ?bool
{
return $this->isRead;
}
public function setIsRead(?bool $isRead): self
{
$this->isRead = $isRead;
return $this;
}
public function getSentAt(): ?\DateTimeImmutable
{
return $this->sentAt;
}
public function setSentAt(?\DateTimeImmutable $sentAt): self
{
$this->sentAt = $sentAt;
return $this;
}
}
Entity privateMessage
use App\Repository\PrivateMessageRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=PrivateMessageRepository::class)
*/
class PrivateMessage
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $message;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="sender")
*/
private $sender;
/**
* #ORM\ManyToOne(targetEntity=user::class, inversedBy="receiver")
*/
private $recipient;
/**
* #ORM\Column(type="boolean", nullable=true)
*/
private $isRead = 0;
/**
* #ORM\Column(type="datetime_immutable", nullable=true)
*/
private $sentAt;
public function getId(): ?int
{
return $this->id;
}
public function getMessage(): ?string
{
return $this->message;
}
public function setMessage(?string $message): self
{
$this->message = $message;
return $this;
}
public function getSender(): ?User
{
return $this->sender;
}
public function setSender(?User $sender): self
{
$this->sender = $sender;
return $this;
}
public function getRecipient(): ?user
{
return $this->recipient;
}
public function setRecipient(?user $recipient): self
{
$this->recipient = $recipient;
return $this;
}
public function getIsRead(): ?bool
{
return $this->isRead;
}
public function setIsRead(?bool $isRead): self
{
$this->isRead = $isRead;
return $this;
}
public function getSentAt(): ?\DateTimeImmutable
{
return $this->sentAt;
}
public function setSentAt(?\DateTimeImmutable $sentAt): self
{
$this->sentAt = $sentAt;
return $this;
}
}
Could you please use the web debug toolbar to extract the readable query and fire it agains your sql server.
I think your repository dql is wrong - hope i figure it out of the head correct.
You have to go over the message repository, not over the user repo.
You have to select the messages for user a and user b visaverce
$qb = $this->createQueryBuilder('m');
$qb->where(
$qb->expr()->orX(
$qb->expr()->andX(
$qb->expr()->eq('m.sender', ':sender'),
$qb->expr()->eq('m.recipient', ':recipient')
),
$qb->expr()->andX(
$qb->expr()->eq('m.sender', ':recipient'),
$qb->expr()->eq('m.recipient', ':sender')
)
)
)
->setParameter(':sender', $sender)
->setParameter(':recipient', $recipient)
->getQuery()
->getResult()
You say you want the conversation between the two users. Architectural i think, there is a missing table named conversation. Think about that:
A user can have a conversation to one-or-many users
A conversation can have one-or-many message(s)
A message can have a sender and a recipient
Maybe a better solution if you want to have more than one conversation ...
Thank you for your time and tips, i tried your dql request and it return "NULL".
About doing it into the message repo instead of user repo i did it like this because in my entity user i have two methods that can retrieve messages sent and received.
But anyways even trying it inside message repo return an empty array.
I tryed with rawsql and got some good result:
public function stack($id)
{
$rawSql =
"SELECT pm.sent_at as date, pm.message, user.login as login FROM private_message as pm
INNER JOIN user on user.id = pm.sender_id
WHERE pm.sender_id = $id
UNION
SELECT pm.sent_at as date, pm.message, user.login as login FROM private_message as pm
INNER JOIN user on user.id = pm.recipient_id
WHERE pm.recipient_id = $id
ORDER BY date DESC"
;
$conn = $this->getEntityManager()->getConnection()->prepare($rawSql);
$stmt = $conn->executeQuery([$rawSql]);
return $stmt->fetchAll();
}
However this request have some weird behavior specially when i set two different $id variable if i manually set the user id and recipient id it start to duplicate some messages and also the user.login returned is the same for all messages sent and recieved. But still a kind of progress as i have the conversation with this sql request but its not a good solution for long term as the ->fetchAll() method is depreciated and going to be removed from doctrine api in 2023.
By the way the clause UNION in my sql request seem to not have its equal version with DQL do you have any tips to make a UNION with a DQL request ?
I think you are right about adding a conversation table ill have to think back about my db architecture maybe it will make the process more simple and intuitive

Passing POST json object for ArrayCollection data by ajax in Symfony

I want to insert Order data in my Symfony 5 application. OrderDetails ArrayCollection data of an Order entity class. Order and OrderDetails ArrayCollection data get by JSON object ajax post. How to passing POST json object for ArrayCollection data by ajax in Symfony.
Entity Code:
class Order
{
public const NUM_ITEMS = 10;
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $orderNo;
/**
* #ORM\Column(type="datetime")
*/
private $orderDate;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\OneToMany(targetEntity=OrderDetail::class, mappedBy="orders")
*/
private $orderDetails;
public function __construct()
{
$this->orderDetails = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getOrderNo(): ?string
{
return $this->orderNo;
}
public function setOrderNo(string $orderNo): self
{
$this->orderNo = $orderNo;
return $this;
}
public function getOrderDate(): ?\DateTimeInterface
{
return $this->orderDate;
}
public function setOrderDate(\DateTimeInterface $orderDate): self
{
$this->orderDate = $orderDate;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* #return Collection|OrderDetail[]
*/
public function getOrderDetails(): Collection
{
return $this->orderDetails;
}
public function addOrderDetail(OrderDetail $orderDetail): self
{
if (!$this->orderDetails->contains($orderDetail)) {
$this->orderDetails[] = $orderDetail;
$orderDetail->setOrders($this);
}
return $this;
}
public function removeOrderDetail(OrderDetail $orderDetail): self
{
if ($this->orderDetails->contains($orderDetail)) {
$this->orderDetails->removeElement($orderDetail);
// set the owning side to null (unless already changed)
if ($orderDetail->getOrders() === $this) {
$orderDetail->setOrders(null);
}
}
return $this;
}
}
JS File Code:
// Creating Order Json Object
var orderObj = { "orderNo":"", "orderDate":"", "name":"" };
orderObj.orderNo = $("#text_name").val();
orderObj.orderDate = $("#text_mobileno").val();
orderObj.name = $("#text_email").val();
// Set 2: Ajax Post
// Here i have used ajax post for saving/updating information
$.ajax({
type: 'POST',
contentType: 'application/json;',
url:'/cart/ordersave',
data: JSON.stringify(orderObj),
dataType: 'json',
success: function (response)
{
// alert(response['data']);
//alert(1);
},
error:function(){
alert('ajax failed');
}
});
Controller Code:
/**
* #Route("/cart/ordersave", name="cart_order_save", methods={"POST"})
*
*/
public function ordersave(Request $request, SessionInterface $session)
{
if ($request->isXMLHttpRequest()) {
$content = $request->getContent();
if (!empty($content)) {
$params = json_decode($content, true);
$order = new Order();
$order->setOrderNo('ON-101/20');
$order->setOrderDate(new \DateTime());
$order->setName($params['name']);
$order->setMobileNo($params['mobileno']);
$order->setEmail($params['email']);
$order->setDeliveryAddress($params['address']);
$order->setCity($params['city']);
$order->setState($params['state']);
$order->setZipcode($params['zipcode']);
$order->setPaymentBy(1);
$order->setDeliveryDate(new \DateTime());
$em = $this->getDoctrine()->getManager();
$em->persist($order);
$em->flush();
$lastId = $order->getId();
$session->set('lastOrderIDSession', $lastId);
}
$this->addFlash('notice', 'Order created successfully!');
return new JsonResponse(array('data' => $lastId));
// return new JsonResponse(array('data' => $params));
}
return new Response('Error!', 400);
}
How to get ArrayCollection data in the controller and insert its database table.
I'd advise you using a symfony form, with a form collection, and it will work by itself. You seem to want to use ajax, and even with forms, you can submit the form in javascript without reloading the page.
This will help : https://symfony.com/doc/current/form/form_collections.html
If you really don't want to do that, well you totally can submit an array with the order details data, then iterate on it, create an OrderDetail entity for each, persist them, etc...

Request a linked field in symfony

I have a page that displays information about a movie. I recover in GET the id of the film. What I would like to do is retrieve the comments for each film (there is a filmId column in my table linked to the primary id of the film table)
/**
* #Route("/user/film/{id}", name="film")
*/
public function film(FilmRepository $repo, CommentRepository $comRepo, EntityManagerInterface $em, Request $req, $id)
{
$film = $repo->find($id);
$comments = $comRepo->findBy(array('id' => $id));
return $this->render('film/film.html.twig', [
'controller_name' => 'FilmController',
'film' => $film,
'comments' => $comments
]);
}
when I make a $comments = $comRepo->findBy(array('id' => $id)); I get some comments, but based on their id and NOT the film id (the comment with id 1 will be displayed on the film with id 1, but for example a comment with id 4 and the filmId a 1 will not appear on film 1, but on the film with id 4)
I tried to access the filmId field by simply making a $comments = $comRepo->findBy(array ('filmId' => $ id)); but i get the error :
An exception occurred while executing 'SELECT t0.id AS id_1, t0.content AS content_2, t0.created_at AS created_at_3, t0.author_id AS author_id_4 FROM comment t0 WHERE comment_film.film_id = ?' with params ["1"]:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'comment_film.film_id' in 'where clause'
I tried a personalized request with, in my Comment repository:
public function findAllWithFilmId($filmId)
{
$em = $this->getEntityManager();
$query = $em->createQuery(
'SELECT c
FROM App\Entity\Comment c
WHERE c.filmId = :filmId'
)->setParameter('filmId', $filmId);
return $query->getResult();
}
But it doesn't seem to work..
Where do I go to make a request like this ?
How to modify the request, which seems erroneous, from symfony without disorganizing everything? or is there a better method to correct the problem?
This is my Comment Entity
<?php
namespace App\Entity;
use App\Entity\Film;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\CommentRepository")
*/
class Comment
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="comments")
* #ORM\JoinColumn(nullable=false)
*/
private $author;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Film", inversedBy="comments")
* #ORM\JoinColumn(nullable=false)
*/
private $filmId;
/**
* #ORM\Column(type="text")
*/
private $content;
/**
* #ORM\Column(type="datetime")
*/
private $createdAt;
public function getId(): ?int
{
return $this->id;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): self
{
$this->author = $author;
return $this;
}
public function getFilmId(): ?Film
{
return $this->filmId;
}
public function setFilmId(?Film $filmId): self
{
$this->filmId = $filmId;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
}
I think it is possible that the error comes from annotations, because starting on symfony during the make: entity, I defined types relations which I corrected later in phpmyadmin, but not the code. For example we can see that filmId is in ManyToMany, but I think it should be in OneToOne (FilmId can only have one id and an id can only correspond to one filmId), but I'm afraid that if I change certain things it breaks everything.
If you have set up your ORM relations correctly, it should be as simple as:
$film = $repo->find($id);
$comments = $film->getComments();
You might be missing a mapping in Film.php.
Here's an XML example, should be easy enough to convert to annotations:
In film:
<one-to-many field="comments" target-entity="App\...\Comments" mapped-by="film"/>
In comments:
<many-to-one field="film" target-entity="App\...\Film" inversed-by="comments"/>
First of all, I advise you to read more about the relations between entities.
Because, the current annotations says that you can have a lot of comments on many films. It's not right. One comment may belong to one film. One movie can have many comments.
Also, I want to note that, as far as I know, #JoinColumn should be in a child entity, that is, where the link to FK is contained.
Therefore, your entities should look like this:
Comment:
<?php
namespace App\Entity;
use App\Entity\Film;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\CommentRepository")
*/
class Comment
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="comments")
*/
private $author;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Film", inversedBy="comments")
* Here we set property for our table and property of foreign table to map our comment to the right film
* nullable, because comment couldn't be without film
* #ORM\JoinColumn(name="film_id", referencedColumnName="id", nullable=false)
*/
private $film;
/**
* #ORM\Column(type="text")
*/
private $content;
/**
* #ORM\Column(type="datetime")
*/
private $createdAt;
public function getId(): ?int
{
return $this->id;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): self
{
$this->author = $author;
return $this;
}
public function getFilmId(): ?Film
{
return $this->filmId;
}
public function setFilmId(?Film $filmId): self
{
$this->filmId = $filmId;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getCreatedAt(): ?DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
}
Film:
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\FilmRepository")
*/
class Film
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="film")
*/
private $comments;
public function __construct()
{
$this->comments = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
return $this;
}
public function getComments(): Collection
{
return $this->comments;
}
public function setComments(Collection $comments): Film
{
$this->comments = $comments;
return $this;
}
}
So, now, you can retrieve your comments via:
/**
* #Route("/user/film/{id}", name="film")
*/
public function film($id)
{
/** #var null|EntityManager $entityManager */
$entityManager = $this->get('doctrine.orm.entity_manager');
if (null == ($film = $entityManager->getRepository(Film::class)->find($id))){
throw new NotFoundHttpException('Film not found');
}
$comments = $film->getComments();
return $this->render('film/film.html.twig', [
'film' => $film,
'comments' => $comments
]);
}

Can't bind form data to doctrine find function. "ORMInvalidArgumentException"

I'm trying to make a simple guestbook in Symfony 4, my goal is that you can add a message to the guestbook but before that, it needs to be internally activated.
I'm now working on the activating site, but there is a problem I can't really fix. The error message is as follows:
Binding entities to query parameters only allowed for entities that
have an identifier.
What i'm trying to do is, after you've typed in the ID of the non-activated message in the Activator Form, it takes the data (ID) from the form that was given and Doctrine finds the specific row of that ID. Then, it changes the rows smallint (not boolean) "isActive" to 1, so the Guestbook know which messages to show.
At " $message = $repository->find($id); " symfony couldn't bind my form data with the query parameters. I've already tried this answer but it didn't work either.
GBActivatorController.php:
use App\Entity\Guestbook;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class GBActivatorController extends AbstractController
{
public function index(Request $request)
{
//sets up the entity guestbook and the entitymanager from doctrine
$guestbook = new Guestbook();
$entityManager = $this->getDoctrine()->getManager();
//get all messages
$list = $this->getDoctrine()
->getRepository(Guestbook::class)
->findAll();
//create form for activating a non-activated message
$activator = $this->createFormBuilder($guestbook)
->add('id', NumberType::class,
array(
'mapped' => false,
))
->add('activate', SubmitType::class, ['label' => 'Activate'])
->getForm();
$activator->handleRequest($request);
/*when the submit button is clicked, get the data and
find the row with the specific id that was given.*/
if($activator->isSubmitted())
{
//gets the data from the form
$id = $activator->getData();
//sets up repository, so i dont need to type it again
$repository = $this->getDoctrine()->getRepository(Guestbook::class);
//(should) find the row
$message = $repository->find($id);
//activates row. (isActive = 1 instead of isActive = 0)
$message->setIsActive(1);
//persist and then execute to table
$entityManager->persist($message);
$entityManager->flush();
}
//renders the template
return $this->render('GBActivator.html.twig', array(
'list' => $list,
'activator' => $activator->createView()
));
}
}
Entity/Guestbook.php:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\GuestbookRepository")
*/
class Guestbook
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
public $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $email;
/**
* #ORM\Column(type="string", length=255)
*/
private $text;
/**
* #ORM\Column(type="smallint")
*/
private $isActive;
public function setId(Array $id)
{
$this->id = $id;
}
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;
}
public function getText(): ?string
{
return $this->text;
}
public function setText(string $text): self
{
$this->text = $text;
return $this;
}
public function getIsActive(): ?int
{
return $this->isActive;
}
public function setIsActive(int $isActive): self
{
$this->isActive = $isActive;
return $this;
}
}
Thank you Eakethet.
My problem was that i demanded an array instead of a string. Stupid me. I changed
public function setId(Array $id)
{
$this->id = $id;
}
to
public function setId(string $id)
{
$this->id = $id;
}

how to create an object with a user attached in symfony

I'm trying to create a product that the current authenticated user created.
The user has a relationship with the product entity, i need to make a way for a user to create product with the user associated with it.
I'm following this tutorial, but it doesn't cover how to store a product with a current user
This is what i have so far
ProductController.php
public function create(Request $request)
{
$category = new Category();
$category->setName($request->get('category'));
$user = new User();
// how would i get the current user and set it to a product.
$entityManager = $this->getDoctrine()->getManager();
$product = new Product();
$product->setName($request->get('title'));
$product->setPrice($request->get('price'));
$product->setDescription($request->get('description'));
$product->setCategory($category);
$entityManager->persist($category);
$entityManager->persist($product);
$entityManager->flush();
return $this->redirectToRoute('products');
}
Should i use this method or try something else ?
Entity\User.php
public function addProduct(Product $product): self
{
if (!$this->products->contains($product)) {
$this->products[] = $product;
$product->setUser($this);
}
return $this;
}
Entity\Product.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\ProductRepository")
*/
class Product
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=190)
*/
private $name;
/**
* #ORM\Column(type="integer")
*/
private $price;
/**
* #ORM\Column(type="text")
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="products")
* #ORM\JoinColumn(nullable=false)
*/
private $category;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="products")
* #ORM\JoinColumn(nullable=false)
*/
private $user;
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 getPrice(): ?int
{
return $this->price;
}
public function setPrice(int $price): self
{
$this->price = $price;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getCategory(): ?Category
{
return $this->category;
}
public function setCategory(?Category $category): self
{
$this->category = $category;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
}
As I can see, your relation works through addProduct() method, but in your controller, you don't call addProduct() anywhere.
try following...
$entityManager->persist($user) // you forgot to persist a new User
$entityManager->persist($category);
$entityManager->persist($product);
$user->addProduct(product)
$entityManager->flush(); // now try to flush...
Offtopic and a bit
constructive criticism
Just by looking at your controller I assume you playing around with Symfony and in particular with doctrine. If it is so, consider following. If not then just ignore it ;)
rename Product->user to Product->createdBy This naming convention makes it more obvious.
For that case it's better to switch from a bidirectional relation (your current state) to a unidirectional (google for it, but in short -> just throw away inversedBy and mappedBy part in you Product <-> User relation )

Categories