user2305673
user2305673

Reputation: 167

Symfony: In my "add" controller, how can I make this associated entity get updated?

I have 2 entities: Article and Author. Here's my "add" controller for ArticleController.php. I'm trying to see if the author exists (based on email). If he does exist, I'd like to grab the new first/last name and update the existing entry. If he doesn't exist then I'd like to add the new one it.

New Authors get added just fine if I remove my "if" and setAuthor line. I can't get the names of existing Authors to get updated as I'd expect though!

public function newAction(Request $request)
{
    $article = new article();
    $form = $this->createForm('AppBundle\Form\articleType', $article);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $em = $this->getDoctrine()->getManager();
        // check to see if the email already exists.
        $existingAuthor = $em
            ->getRepository('AppBundle:Author')
            ->findOneByEmail($article->getAuthor()->getEmail());

        if ($existingAuthor) {

            //if the email does exist, grab the incoming name and update the existing name with it.
            $existingAuthor->setFirstName($article->getAuthor()->getFirstName());
            $existingAuthor->setLastName($article->getAuthor()->getLastName());
            $author = $existingAuthor;

        } else {
            //Other wise it's a new author. Set the creation timestamp.
            $date = new \DateTime("now");
            $article->getAuthor()->setCreatedDate($date);
        }

        $article->setAuthor($author);

        //Set Created Date
        $date = new \DateTime("now");
        $article->setCreatedDate($date);

        //Persist to database.

        $em->persist($article);
        $em->flush($article);

        return $this->redirectToRoute('article_show', array('id' => $article->getId()));

    }

    return $this->render('article/new.html.twig', array(
        'article' => $article,
        'form' => $form->createView(),
    ));
}

Here's the Article entity

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
 * Article
 *
 * @ORM\Table(name="article")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ArticleRepository")
 * @UniqueEntity(fields={"name"}, message="Note: That article already existed.")
 */
class Article
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, unique=true)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="text", nullable=true)
     */
    private $description;

    /**
     * @var string
     *
     * @ORM\Column(name="thumbnail", type="string", length=255, nullable=true)
     */
    private $thumbnail;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="created_date", type="datetime")
     */
    private $createdDate;

    /**
     * @ORM\ManyToOne(targetEntity="Author", inversedBy="articles", cascade={"persist"})
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     * @Assert\Valid()
     */
    private $author;


    /**
     * @ORM\OneToMany(targetEntity="Review", mappedBy="article")
     */
    private $reviews;

    public function __construct()
    {
        $this->reviews = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Article
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set description
     *
     * @param string $description
     *
     * @return Article
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Get description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Set thumbnail
     *
     * @param string $thumbnail
     *
     * @return Article
     */
    public function setThumbnail($thumbnail)
    {
        $this->thumbnail = $thumbnail;

        return $this;
    }

    /**
     * Get thumbnail
     *
     * @return string
     */
    public function getThumbnail()
    {
        return $this->thumbnail;
    }

    /**
     * Set createdDate
     *
     * @param \DateTime $createdDate
     *
     * @return Article
     */
    public function setCreatedDate($createdDate)
    {
        $this->createdDate = $createdDate;

        return $this;
    }

    /**
     * Get createdDate
     *
     * @return \DateTime
     */
    public function getCreatedDate()
    {
        return $this->createdDate;
    }

    /**
     * Set authorId
     *
     * @param integer $authorId
     *
     * @return Article
     */
    public function setAuthorId($authorId)
    {
        $this->authorId = $authorId;

        return $this;
    }

    /**
     * Get authorId
     *
     * @return int
     */
    public function getAuthorId()
    {
        return $this->authorId;
    }

    /**
     * Set author
     *
     * @param \AppBundle\Entity\Author $author
     *
     * @return Article
     */
    public function setAuthor(\AppBundle\Entity\Author $author = null)
    {
        $this->author = $author;

        return $this;
    }

    /**
     * Get author
     *
     * @return \AppBundle\Entity\Author
     */
    public function getAuthor()
    {
        return $this->author;
    }

    /**
     * Add review
     *
     * @param \AppBundle\Entity\Review $review
     *
     * @return Article
     */
    public function addReview(\AppBundle\Entity\Review $review)
    {
        $this->reviews[] = $review;

        return $this;
    }

    /**
     * Remove review
     *
     * @param \AppBundle\Entity\Review $review
     */
    public function removeReview(\AppBundle\Entity\Review $review)
    {
        $this->reviews->removeElement($review);
    }

    /**
     * Get reviews
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getReviews()
    {
        return $this->reviews;
    }

    public function __toString() {
        return $this->name;
    }

}

Here's the form:

The form

Thanks in advance for any response. Oh, also, is this an acceptable place for such logic? I'm going to move the if into a helper class to be used in other controllers ... but is a controller a good spot for calling this logic even?

UPDATE: Based on sakhunzai's answer this is currently working. These are 2 methods in my article controller.

But I still have some questions regarding best practices. IF anyone can answer those (in a comment on sakhunzai's answer) I'd be very grateful!

   protected function getAuthor(\AppBundle\Entity\Author $author){

        $em = $this->getDoctrine()->getManager();
        $email = $author->getEmail();

        $existingAuthor = $em->getRepository('AppBundle:Author')->findOneByEmail($email);

        if($existingAuthor){
            $existingAuthor->setFirstName($author->getFirstName());
            $existingAuthor->setLastName($author->getLastName());
            $author = $existingAuthor;
        } else {
            $date = new \DateTime("now");
            $author->setCreatedDate($date);
            $em->persist($author);
        }

        $em->flush();

        return $author;
    }

    /**
     * Creates a new article entity.
     *
     * @Route("/new", name="article_new")
     * @Method({"GET", "POST"})
     */
    public function newAction(Request $request)
    {
        $article = new Article();
        $form = $this->createForm('AppBundle\Form\ArticleType', $article);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {


            //Update existing author or create new
            $em = $this->getDoctrine()->getManager();
            $author = $this->getAuthor($article->getAuthor());
            //Set the author
            $article = $form->getData();
            $article->setAuthor($author);
            //Set Created Date
            $date = new \DateTime("now");
            $article->setCreatedDate($date);
            $em->persist($article);
            $em->flush($article);




            return $this->redirectToRoute('article_show', array('id' => $article->getId()));

        }

        return $this->render('article/new.html.twig', array(
            'article' => $article,
            'form' => $form->createView(),
        ));
    }

Upvotes: 0

Views: 97

Answers (2)

sakhunzai
sakhunzai

Reputation: 14470

I think you need to do something like this (not tested) e.g add new method getAuthor in your article controller and call as follow

    /**
     * @param Request $request
     * @return AppBundle\Entity\Author;
     */
    protected function getAuthor(EntityManager $em, Request $request){

        $email = $request->get('email');

        $author = $em->getRepository('AppBundle:Author')->findOneByEmail($email);

        if(!$author){
            $author= new Author();
            $author->setLastName($email);
            $author->setFirstName($request->get('first_name'));
            $author->setLastName($request->get('last_name'));
            $em->persist($author);
            $em->flush();
        }

        return $author;
    }


    public function newAction(Request $request)
    {
        $article = new article();
        $form = $this->createForm('AppBundle\Form\articleType', $article);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {

            $em = $this->getDoctrine()->getManager();
            $author = $this->getAuthor($em,$request);

            $article = $form->getData();
            $article->setAuthor($author);
            $em->persist($article);
            $em->flush($article);

            return $this->redirectToRoute('article_show', array('id' => $article->getId()));

        }

        return $this->render('article/new.html.twig', array(
            'article' => $article,
            'form' => $form->createView(),
        ));
    }

Upvotes: 1

Simas Joneliunas
Simas Joneliunas

Reputation: 3118

Is the cascade part of the relation set properly (i.e. below)?

 /**
 * @OneToOne(... cascade={"persist"})
 */

Upvotes: 0

Related Questions