2017-02-20 4 views
0

У меня есть 2 объекта: статья и автор. Вот мой контроллер «add» для ArticleController.php. Я пытаюсь проверить, существует ли автор (по электронной почте). Если он существует, я хотел бы получить новое имя/фамилию и обновить существующую запись. Если он не существует, я бы хотел добавить его.Symfony: В моем контроллере «добавить», как я могу заставить этот связанный объект получить обновление?

Новые авторы добавляются просто отлично, если я удаляю строку «if» и setAuthor. Я не могу заставить имена существующих авторов обновляться, как я ожидал!

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(), 
    )); 
} 

Вот статья 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; 
    } 

} 

Вот форма:

The form

Заранее спасибо за любой ответ. О, также, это приемлемое место для такой логики? Я собираюсь переместить if в класс помощника, который будет использоваться в других контроллерах ... но является контроллером хорошим местом для вызова этой логики?

ОБНОВЛЕНИЕ: Основываясь на ответе сахунзай, в настоящее время он работает. Это два метода в моем контроллере.

Но у меня все еще есть некоторые вопросы относительно лучших практик. Если кто-нибудь может ответить на это (в комментарии к ответе сахунзая), я был бы очень благодарен!

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(), 
     )); 
    } 
+0

строка '-> findOneByEmail ($ article-> getAuthor() -> getEmail()); 'кажутся неоднозначными. Первая строка вашей функции - это создание новой статьи, и я подозреваю, что ей еще не назначен автор, а это означает, что указанная выше строка, где вы пытаетесь 'getAuthor()', вернет значение null. – sakhunzai

+0

Спасибо за ответ. Вы правы, что он вернет NULL, но только если адрес электронной почты ($ article-> getAuthor() -> getEmail()) не существует ... $ article-> getAuthor() возвращает идеальные данные прямо перед тем, как статья сохранится ... автор, установленный в $ article-> setAuthor ($ author), просто не обновляется. Я не понимаю, как упорство работает? Я думал, что он обновил эти связанные данные. ЕСЛИ это не лучший способ справиться с этим? Спасибо! – user2305673

+0

, если автор является допустимым автором, вам не нужно обновлять его снова '$ article-> setAuthor ($ author);'. Но я подозреваю, что вы пытаетесь создать «Article» и «Author» за один раз. Пожалуйста, добавьте скриншот формы, если возможно – sakhunzai

ответ

1

Я думаю, что вам нужно сделать что-то вроде этого (не проверено), например, добавить новый метод getAuthor в контроллере статьи и называем следовать

/** 
    * @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(), 
     )); 
    } 
+0

Большое вам спасибо! Я смог заставить его работать на основе вашего ответа. У меня есть некоторые вопросы, которые вышли из него, хотя я надеюсь, что вы не возражаете ответить. 1: Что стоит за :)? 2: Зачем передавать $ em вместо получения новой эффективности памяти? 3: Зачем передавать запрос вместо автора напрямую - я сделал что-то неправильно, изменив свой метод, чтобы принять автора?4: Мне сказали, что если я сохраню объект, полученный в $ em, он просто обновится и не будет вставляться. это, похоже, не так (он потерпел крушение, прежде чем двигаться продолжался внутри другого). был ли я ошибся? – user2305673

+0

1) исправлена ​​проблема «sth» извините за плохой английский, 2) да лучше избегать дополнительных вызовов/и создавать объекты 3) ваш код запутан, потому что автор существует, когда вы вызываете '$ article-> getAuthor()' в первом место и намерение не видно из кода, ваш поток может быть правильным при обновлении и существующей статье не для новой статьи. – sakhunzai

+0

4) прочитайте это http://symfony.com/doc/current/doctrine.html, ваши концепции будут очищены, а кто-то сказал вам ложь – sakhunzai

0

Правильно ли установлена ​​каскадная часть отношения (т. Е. Ниже)?

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

Это, насколько я знаю. Благодарю. Я включил объект статьи для справки. – user2305673