如何在Symfony中设置数据变换器以重用现有实体?

编程入门 行业动态 更新时间:2024-10-28 04:27:11
本文介绍了如何在Symfony中设置数据变换器以重用现有实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在Symfony的文章编辑器中使用内置的标记功能:

控制器 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ {$ $ $ $ $ $ $ $ $ $ $ $ $ - > getDoctrine() - > getManager(); // $ article = ... $ form = $ this-> createForm(new ArticleType(),$ article); $ form-> handleRequest($ request); if($ form-> isValid()){ $ em-> persist($ article); $ em-> flush(); return $ this-> redirect($ this-> generateUrl('acme_edit_success')); } return $ this-> render('AcmeBundle:Main:index.html.twig',array('form'=> $ form-> createView())); } }

表单

标签表单注册为具有 @Doctrine 参数的服务,因此我可以在类中使用实体管理器。标签表单嵌入文章格式。

ArticleType.php

class ArticleType extends AbstractType { public function buildForm(FormBuilderInterface $ builder,array $ options) { $ builder - > add('content' ) - > add('tags','collection',array('type'=>'acme_bundle_tagtype','allow_add'=> true, '$'$'$'$'$'$'$'$'$'$'$'$'$' } public function setDefaultOptions(OptionsResolverInterface $ resolver) { $ resolver-> setDefaults(array('data_class'=> Acme\Bundle\Entity\Article','cascade_validation'=> true )); } public function getName() { return'acme_bundle_articletype'; } }

TagType.php

class TagType extends AbstractType { private $ entityManager; public function buildForm(FormBuilderInterface $ builder,array $ options) { $ transformer = new TagTransformer($ this-> entityManager); $ builder-> add( $ builder-> create('name') - > addModelTransformer($ transformer)); } 函数__construct(\Doctrine\Bundle\DoctrineBundle\Registry $ doctrine){ $ this-> entityManager = $ doctrine-> getManager( ); } public function setDefaultOptions(OptionsResolverInterface $ resolver) { $ resolver-> setDefaults(array('data_class'=> Acme\Bundle\Entity\Tag')); } public function getName() { return'acme_bundle_tagtype'; } }

数据变压器

我创建了这个数据变换器来检查给定的标签是否已经存在,然后将标签对象转换为数据库中已存在的标签对象:

class TagTransformer实现DataTransformerInterface { / ** * @var ObjectManager * / private $ om; / ** * @param ObjectManager $ om * / public function __construct(ObjectManager $ om) { $ this - > om = $ om; } public function transform($ tag) { if(null === $ tag){ return''; } return $ tag; } public function reverseTransform($ name) { if(!$ name) return null; $ tag = $ this-> om - > getRepository('AcmeBundle:Tag') - > findOneByName($ name); if(!$ tag){ $ tag = new Tag(); $ tag-> setName($ name); } return $ tag; } }

当我尝试保存一个已经存在的文章标签, reverseTransform()函数成功返回原始的标签对象,但是, DBAL将对象转回到一个字符串,其 __ toString( )方法,而Doctrine仍然启动一个 INSERT 查询而不是 UPDATE ,所以我得到下一个错误:

执行'INSERT INTO Tag(name) VALUES(?)时发生异常'with params [{}]:

SQLSTATE [23000]:完整性约束违规:1062重复条目'现有标签'用于密钥'UNIQ_0123456789ABCDE' / p>

我该如何解决?当我输入已经使用的标签名称时,我希望Symfony在文章标签关系中使用相同的标签。实体类出现在我之前关于如何避免与Doctrine的多对多关系中重复输入的问题的问题。

解决方案

您的变压器有一个错误。而不是检查名称是否为null,您应该验证是否返回标签:

if(! $ tag){ $ tag = new Tag(); $ tag-> setName($ name); }

您也不需要保留标签,因为默认情况下,doctrine将级联持有所有相关实体。

完整方法:

public function reverseTransform($ name) { if(!$ name){ return null; } $ tag = $ this-> om - > getRepository('AcmeBundle:Tag') - > findOneByName($ name); if(!$ tag){ $ tag = new Tag(); $ tag-> setName($ name); } return $ tag; }

I'm working on an article editor in Symfony with built-in tagging capability:

The controller

class MainController extends Controller { public function indexAction(Request $request, $id) { $em = $this->getDoctrine()->getManager(); // $article = ... $form = $this->createForm(new ArticleType(), $article); $form->handleRequest($request); if ($form->isValid()) { $em->persist($article); $em->flush(); return $this->redirect($this->generateUrl('acme_edit_success')); } return $this->render('AcmeBundle:Main:index.html.twig', array( 'form' => $form->createView() )); } }

The forms

The tag form is registered as a service with the @Doctrine argument, so I can use the entity manager inside the class. The tag form is embed inside the article form.

ArticleType.php

class ArticleType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('content') ->add('tags', 'collection', array( 'type' => 'acme_bundle_tagtype', 'allow_add' => true, 'allow_delete' => true, 'by_reference' => false )) ->add('save', 'submit') ; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Acme\Bundle\Entity\Article', 'cascade_validation' => true )); } public function getName() { return 'acme_bundle_articletype'; } }

TagType.php

class TagType extends AbstractType { private $entityManager; public function buildForm(FormBuilderInterface $builder, array $options) { $transformer = new TagTransformer($this->entityManager); $builder->add( $builder->create('name') ->addModelTransformer($transformer) ); } function __construct(\Doctrine\Bundle\DoctrineBundle\Registry $doctrine) { $this->entityManager = $doctrine->getManager(); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Acme\Bundle\Entity\Tag' )); } public function getName() { return 'acme_bundle_tagtype'; } }

The data transformer

I created this data transformer to check if the given tag already exists and then transform the tag object to the one that already exists in the database:

class TagTransformer implements DataTransformerInterface { /** * @var ObjectManager */ private $om; /** * @param ObjectManager $om */ public function __construct(ObjectManager $om) { $this->om = $om; } public function transform($tag) { if (null === $tag) { return ''; } return $tag; } public function reverseTransform($name) { if (!$name) return null; $tag = $this->om ->getRepository('AcmeBundle:Tag') ->findOneByName($name) ; if (!$tag) { $tag = new Tag(); $tag->setName($name); } return $tag; } }

When I try to save an article with an already existing tag, the reverseTransform() function successfully returns the original tag objects, but the DBAL converts the object back to a string by its __toString() method, and Doctrine still initiates an INSERT query instead of UPDATE, so I get the next error:

An exception occurred while executing 'INSERT INTO Tag (name) VALUES (?)' with params [{}]:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'An Existing Tag' for key 'UNIQ_0123456789ABCDE'

How can I fix this? When I enter a tag name that's already in use, I want Symfony to use the same tag in the article-tag relationship. The entity classes appear in my previous question about how to avoid duplicate entries in a many-to-many relationship with Doctrine.

解决方案

There's one mistake in your transformer. Instead of checking if name is null you should verify if a tag was returned:

if (!$tag) { $tag = new Tag(); $tag->setName($name); }

You also don't need to persist the tag since by default doctrine will cascade persist all the related entities.

Full method:

public function reverseTransform($name) { if (!$name) { return null; } $tag = $this->om ->getRepository('AcmeBundle:Tag') ->findOneByName($name) ; if (!$tag) { $tag = new Tag(); $tag->setName($name); } return $tag; }

更多推荐

如何在Symfony中设置数据变换器以重用现有实体?

本文发布于:2023-10-26 11:11:10,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1529963.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:变换器   实体   数据   如何在   Symfony

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!