给出了“Doctrine\Common\Collections\ArrayCollection”、“Doctrine\ORM\PersistentCollection”类型的预期参数

问题描述 投票:0回答:2

我在标签和文章实体之间有多对多关系,插入效果很好,但编辑表单(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”。帮助我!

php symfony doctrine edit arraycollection
2个回答
3
投票

当你期望在

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);
}

0
投票

这两个类都是一个

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();
    } 
}
© www.soinside.com 2019 - 2024. All rights reserved.