symfony - 给出的预期参数类型为 "Doctrine\Common\Collections\ArrayCollection","Doctrine\ORM\PersistentCollection"

标签 symfony doctrine edit arraycollection

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

TagType.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';
 }
}

ArticleType.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”。帮助我!

最佳答案

当您希望在 StringToTagsTransformer 中获取 ArrayCollection 时,问题就出现了

if (!($value instanceof ArrayCollection)) {
    throw new UnexpectedTypeException($value, 
    'Doctrine\Common\Collections\ArrayCollection');
}

实际上,发生这种情况是因为 Doctrine 中的 ArrayCollection 类仅用于急切获取的关系,并且默认情况下关系始终是延迟获取的。因此,您必须急切地获取它,或者只是检查 $value 是否是 Doctrine\Common\Collections\Collection 的实例,这是两个类实现的接口(interface)

use Doctrine\Common\Collections\Collection;

if (!($value instanceof Collection)) {
    throw new UnexpectedTypeException($value, Collection::class);
}

关于symfony - 给出的预期参数类型为 "Doctrine\Common\Collections\ArrayCollection","Doctrine\ORM\PersistentCollection",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48345598/

相关文章:

php - 如何将 andWhere 和 orWhere 与 Doctrines Criteria 结合起来

php - Symfony 4 和 mongodb :generate:documents

php - Zend + 表关系上的 Doctrine 错误

java - Android项目中assets-文件夹的访问方式是什么?

security - _switch_user 不起作用

php - Assetic(与 Symfony 2)在运行 'assetic:dump' 时更改图像文件的名称

json - 如何一次在 jq 中设置多个路径值?

c - 从编辑控件中删除键盘焦点

javascript - Symfony 4 - 无法在 formBuilder 中自定义表单字段的 attr

php - Symfony2 学说 : How to select users that are not in groups with doctrine query builder