2017-02-21 23 views
1

this tutorialを実装しています。 Tagエンティティがすでに存在する場合、私は新しいものを作成することを決定することができるように埋め込みフォームのコレクション:エンティティが存在するかどうかを確認

/** 
* @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; 

    } 

がどのように私は、neweditコントローラで、確認することができます。しかし、私の場合にはTagエンティティは、ユニークなname性質を持っています。 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

あなたはTaskType属性::クラスを投稿していないので、私はあなたがタグを取得するために、このコードスニペットを使用していると推測されます:あなたが見

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

は、symfonyのフォームの作業方法は、彼らがシリアライズされユーザからエンティティに戻ったデータ。タグコレクションを作成するとき、実際に何をしているのかは、タグ名を内部的なタグオブジェクトにシリアル化することです。したがってコードのこの部分は:

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

実際には文字列ではなくタグオブジェクトの配列を取得します。既存のタグを確認するために、配列をループしているとき、理由は次のとおりです。

foreach ($tags as $tagName) {} 

$ tagNameには、実際には、タグ名ではありません。クラスタグのオブジェクトです。あなたはtagNameをすることにより、タグを見つけようとしているとき:

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

を、あなたが実際にあるか名前を照会する教義リポジトリにタグオブジェクトを渡してやって。今は内部的にはもちろん、オブジェクトを文字列と比較することができないので、文字列に変換しようとします。このため、エラーが発生しています。

あなたがやろうとしているものを達成するためには、あなたが最初にする必要があります:それは実際にはないので、この時点ではtagNameの命名を変更した場合

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

(それもいいだろう名前、そのオブジェクト)、データベース内にタグがある場合は、$ em-> remove()を介してtagName変数に保存したオブジェクトを削除し、新たに見つかったタグをタスクに追加する必要があります。

+0

にある{{tag.name}}というタグを正確に '$ newTag-> setName($ tagName);という行に表示します; $ tagNameはオブジェクトを文字列に変換する' __toString() 'を探しています、それは存在しないので、...良いキャッチ – sakhunzai

0

いいえ、これはtasks_listにリダイレクトされています。これはTagと表示されますが、そのオブジェクトの文字列表現はありません。

このエラーを回避するには、TagエンティティあなたがエンティティTag$taskscascade={"persist"}を持って

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

こんにちは、それは理由ではありません。タスクリストページ – blahblah

0

に次の方法を紹介します。まだ、あなたは$tagの後に$taskを維持しています。 cascade={"persist"}$taskから削除し、を$tagsに入れてTaskエンティティに入れて差異があるかどうかを確認してください。

1

データトランスフォーマーを使用する必要があります。参考:

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

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

出来上がり: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クラスでは、このコードを追加します!あなたのタグがすでに存在する場合は、そのタグが見つけられ、あなたのタスクにリンクされます。

関連する問題