我在标签和文章实体之间有多对多关系,插入效果很好,但编辑表单(editAction 函数)的创建不起作用。 所有代码都在那里:
Article.php
<?php
namespace Diapalema\DiapalemaBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
class Article
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="titre", type="string", length=255)
*/
private $titre;
/**
* @var \DateTime
*
* @ORM\Column(name="created", type="datetimetz")
*/
private $created;
/**
* @var \DateTime
*
* @ORM\Column(name="updated", type="datetimetz")
*/
private $updated;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="article", cascade=
{"persist"})
*/
private $auteur;
/**
* BlogArticle constructor.
* @param \DateTime $created
* @param \DateTime $updated
*/
public function __construct()
{
$this->created = $created;
$this->updated = $updated;
$this->tags = new ArrayCollection();
}
public function addTag(Tag $tag)
{
$this->tags->add($tag);
return $this;
}
public function addTags($tags)
{
foreach($tags as $tag){
$this->addTag($tag);
}
return $this;
}
public function removeTag(Tag $tag)
{
$this->tags->removeElement($tag);
return $this;
}
public function removeTags($tags)
{
foreach($tags as $tag){
$this->removeTag($tag);
}
return $this;
}
public function setTags(Tag $tag)
{
$this->tags[] = $tag;
return $this;
}
/**
* Get tags
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getTags()
{
return $this->tags;
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
}
标签.php
class Tag
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="tagname", type="string", length=255)
*/
private $tagname;
/**
*
@ORM\ManyToMany(targetEntity="Diapalema\DiapalemaBundle\Entity\Article",
mappedBy="tags", cascade={"persist","remove"})
*/
private $articles;
/**
* Tag constructor.
*/
public function __construct()
{
$this->articles = new ArrayCollection();
}
/**
* @param Article $articles
*/
public function setArticles($articles)
{
$this->articles = $articles;
}
public function getArticles()
{
return $this->articles;
}
public function addArticles(Article $article)
{
$this->articles[] = $article;
$article->addTag($this);
return $this;
}
public function removeArticles(Article $article)
{
$this->articles->removeElement($article);
$article->removeTag($this);
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
}
StringToTagsTransformer.php
<?php
namespace Diapalema\DiapalemaBundle\Form;
use Symfony\Component\Form\DataTransformerInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Collections\ArrayCollection;
use Diapalema\DiapalemaBundle\Entity\Tag;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Ldap\Adapter\ExtLdap\Collection;
class StringToTagsTransformer implements DataTransformerInterface
{
private $om;
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
private function stringToArray($string)
{
$tags = explode(',', $string);
foreach ($tags as &$text) {
$text = trim($text);
}
return array_unique($tags);
}
public function transform($value)
{
if (null === $value) {
return null;
}
if (!($value instanceof ArrayCollection)) {
throw new UnexpectedTypeException($value,
'Doctrine\Common\Collections\ArrayCollection');
}
$tags = array();
foreach ($value as $tag) {
array_push($tags, $tag->getTagname());
}
return implode(',', $tags);
}
public function reverseTransform($value)
{
$tagCollection = new ArrayCollection();
if ('' === $value || null === $value) {
return $tagCollection;
}
if (!is_string($value)) {
throw new UnexpectedTypeException($value, 'string');
}
foreach ($this->stringToArray($value) as $name) {
$tag = $this->om->getRepository('DiapalemaBundle:Tag')
->findOneBy(array('tagname' => $name));
if (null === $tag) {
$tag = new Tag();
$tag->setTagname($name);
$this->om->persist($tag);
}
$tagCollection->add($tag);
}
return $tagCollection;
}
}
标签类型.php
<?php
namespace Diapalema\DiapalemaBundle\Form;
use Diapalema\DiapalemaBundle\Entity\Tag;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TagType extends AbstractType
{
private $om;
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new StringToTagsTransformer($this->om);
$builder->addModelTransformer($transformer);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'data_class' => Tag::class
)
);
}
public function getParent()
{
return TextType::class;
}
public function getName()
{
return 'tag';
}
}
文章类型.php
<?php
namespace Diapalema\DiapalemaBundle\Form;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ArticleType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tags',TagType::class, array(
'required' => false,
'label' => 'form.tag',
'translation_domain' => 'FOSUserBundle',
'attr' => array(
'class' => 'form-control',
'multiple' => true,
))
);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Diapalema\DiapalemaBundle\Entity\Article'
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'diapalema_diapalemabundle_article';
}
}
ArticleController.php
/**
* Displays a form to edit an existing Article entity.
*
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('DiapalemaBundle:Article')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Impossible de trouver
l\'entité concernée.');
}
$editForm = $this->createEditForm($entity);
return $this->
render('DiapalemaBundle:Admin/Layout:edit_article.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView()
));
}
/**
* Creates a form to edit a Article entity.
* @param Article $entity The entity
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Article $entity)
{
$form = $this->createForm(ArticleType::class, $entity);
$form->add('submit', SubmitType::class, array(
'label' => 'form.editbutton',
'translation_domain' => 'FOSUserBundle',
'attr' =>
array(
'class' => 'btn btn-success'
)
));
return $form;
}
服务.yml
services:
app.type.tag:
class: Diapalema\DiapalemaBundle\Form\TagType
arguments: ['@doctrine.orm.entity_manager']
tags:
- { name: form.type, alias: tag }
我有以下错误: 预期参数类型为“Doctrine\Common\Collections\ArrayCollection”、“Doctrine\ORM\PersistentCollection”。帮助我!
当你期望在
ArrayCollection
中获得
StringToTagsTransformer
时,问题就来了
if (!($value instanceof ArrayCollection)) {
throw new UnexpectedTypeException($value,
'Doctrine\Common\Collections\ArrayCollection');
}
实际上发生这种情况是因为 Doctrine 中的
ArrayCollection
类仅用于急切获取的关系,并且默认情况下关系总是延迟获取。所以你必须急切地获取它或者只是检查 $value
是否是 Doctrine\Common\Collections\Collection
的实例,这是两个类实现的接口
use Doctrine\Common\Collections\Collection;
if (!($value instanceof Collection)) {
throw new UnexpectedTypeException($value, Collection::class);
}
这两个类都是一个
Doctrine\Common\Collections\Collection
接口。因此,除了您在任何地方创建集合之外,请在任何地方将其称为界面而不是具体版本。
<?php
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
class X
{
private Collection $collection;
public function __construct()
{
$this->collection = new ArrayCollection();
}
}