2017-02-21 150 views
1

我正在實施this tutorial。但是在我的情況Tag實體具有獨特的name屬性:,嵌入表格集合:檢查實體是否存在

/** 
* @ORM\Entity() 
*/ 
class Tag 
{ 
    /** 
    * @var string 
    * @ORM\Column(name="name", type="string", length=63, unique=true) 
    */ 
    private $name; 

    /** 
    * @ORM\ManyToMany(targetEntity="Task", cascade={"persist"}) 
    * @ORM\JoinTable(name="tasks_tags") 
    */ 
    protected $tasks; 

    } 

我如何檢查是否Tag實體已經存在於newedit控制器,這樣我可以決定創建新的。如果Tag存在,我可以將它添加到新任務。

public function newAction(Request $request) 
{ 
    $task = new Task(); 

    $form = $this->createForm(TaskType::class, $task); 
    $form->handleRequest($request); 

    if ($form->isSubmitted() && $form->isValid()) { 
     $tags = $form->get('tags')->getData(); 

     $em = $this->getDoctrine()->getManager(); 
     foreach ($tags as $tagName) { 
      $tag = $this->getDoctrine()->getRepository('AppBundle:Tag')->findOneBy(array('name' => $tagName)); 
      if (!$tag) { 
       $newTag = new Tag(); 
       $newTag->setName($tagName); 
       $em->persist($newTag); 
      } 
     } 
     $em->persist($task); 
     $em->flush(); 

     return $this->redirectToRoute('tasks_list'); 
    } 
} 

我得到這個錯誤後提交:

Catchable Fatal Error: Object of class AppBundle\Entity\Tag could not be converted to string

我認爲這是因爲提交Task形式之前Tag實體依然存在。

我該如何處理這部分?

回答

3

因爲我們還沒有發佈任務類型::類,我會猜你已經使用這個代碼片段,以獲得標籤:

$builder->add('tags', CollectionType::class, array(
    'entry_type' => TagType::class 
)); 

你看,順便Symfony的形式工作,是他們的序列化你從用戶那裏獲得的數據返回到實體。當你創建一個標籤集合時,你實際做的是將標籤名稱序列化回標籤對象。因此,這部分代碼:

$tags = $form->get('tags')->getData(); 

實際上得到標籤的對象數組,而不是隻是字符串。這就是爲什麼當你循環陣列來檢查現有標籤時:

foreach ($tags as $tagName) {} 

$ tagName實際上並不是標籤名稱。它是類Tag的一個對象。當你試圖通過標記名找標籤:

->findOneBy(array('name' => $tagName)) 

,你實際上在做什麼是合格的學說信息庫中的標籤對象查詢的名稱。現在內部它當然會嘗試將其轉換爲字符串,因爲您無法將對象與字符串進行比較。這就是你遇到錯誤的原因。

爲了達到你正在嘗試做的,你必須首先:

->findOneBy(array('name' => $tagName->getName())) 

(這也將是很好,如果你改變了標記名的命名在這一點上,因爲它實際上不是一個名稱,它是一個對象),那麼如果你在數據庫中發現一個標籤,你應該通過$ em-> remove()在tagName變量中刪除已保存的對象,並將新發現的標籤添加到任務中。

+0

yes和$'newTag-> setName($ tagName);'$ tagName正在嘗試查找'__toString()'將對象轉換爲字符串的行中顯示標記爲{{tag.name} ,這並不存在,因此......良好的捕獲 – sakhunzai

0

不,這是因爲您重定向到tasks_list,將顯示Tag您已堅持,但您沒有該對象的字符串表示形式。

爲了避免這種錯誤,介紹以下方法進入Tag實體

public function __toString() 
{ 
    // This is only an example; you can insert 
    // here whatever you want to display 
    // as tag's string representation 

    return $this->name; 
} 
+0

你好,不,這不是一個原因。我在tasks_list頁面 – blahblah

0

您在Tag實體上$taskscascade={"persist"};但是,您在$tag之後堅持$task。刪除cascade={"persist"}$task並嘗試cascade={"persist"}$tagsTask實體並檢查是否有任何區別。

1

您應該使用數據變形金剛。參考:http://symfony.com/doc/current/form/data_transformers.html

// src/AppBundle/Form/DataTransformer/TagToNameTransformer.php 
namespace AppBundle\Form\DataTransformer; 

use AppBundle\Entity\Tag; 
use Doctrine\Common\Persistence\ObjectManager; 
use Symfony\Component\Form\DataTransformerInterface; 
use Symfony\Component\Form\Exception\TransformationFailedException; 

class TagToNameTransformer implements DataTransformerInterface 
{ 
    private $manager; 

    public function __construct(ObjectManager $manager) 
    { 
     $this->manager = $manager; 
    } 

    /** 
    * Transforms an object (tag) to a string (name). 
    * 
    * @param Tag|null $tag 
    * @return string 
    */ 
    public function transform($tag) 
    { 
     if (null === $tag) { 
      return ''; 
     } 

     return $tag->getName(); 
    } 

    /** 
    * Transforms a string (name) to an object (tag). 
    * 
    * @param string $tagName 
    * @return Tag|null 
    * @throws TransformationFailedException if object (tag) is not found. 
    */ 
    public function reverseTransform($tagName) 
    { 
     // empty tag name? It's optional, so that's ok 
     if (empty($tagName)) { 
      return; 
     } 

     $tag = $this->manager 
      ->getRepository('AppBundle:Tag') 
      ->find($tagName) 
     ; 

     if (null === $tag) { 
      // causes a validation error 
      // this message is not shown to the user 
      // see the invalid_message option 
      throw new TransformationFailedException(sprintf(
       'An tag with name "%s" does not exist!', 
       $tagName 
      )); 
     } 

     return $tag; 
    } 
} 

TagType類添加以下代碼:

class TagType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     // ... your code 

     $builder->get('name') 
      ->addModelTransformer(new TagToNameTransformer($this->manager)); 
    } 
} 

瞧!如果您的標籤已經存在,它將被發現並鏈接到您的任務。