2017-02-21 149 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)); 
    } 
} 

瞧!如果您的标签已经存在,它将被发现并链接到您的任务。