Symfony表单:EntityType,选择标签和相关实体

时间:2016-06-17 10:20:05

标签: php symfony-forms symfony

我有一个实体News和一个相关实体NewsArticle,其中包含一些News属性的翻译(HeadlineSubheader,{{ 1}})。添加/编辑Bodytext记录的表单需要一个字段来选择相关的News,因此我为此目的定义了News字段。每个可选EntityType记录的标签应显示具有特定字段值(默认语言)的News记录的标题。但我怎么能意识到这一点?

即使是我使用NewsArticle方法的第一次尝试也失败了,并显示以下错误消息:

  

捕获致命错误:类Doctrine \ ORM \ PersistentCollection的对象无法转换为字符串

__toString()实体:

News

<?php // src/Acme/Bundle/Entity/News.php namespace Acme\Bundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * @ORM\Entity * @ORM\Table(name="news") */ class News { /** * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\OneToMany(targetEntity="NewsArticle", mappedBy="news", cascade={"persist", "remove"}) */ protected $newsArticle; /** * @ORM\Column(type="string", length=150, unique=false, nullable=false) */ private $ident; /** * @ORM\Column(type="datetime", nullable=true) */ private $validFrom; /** * @ORM\Column(type="datetime", nullable=true) */ private $validTo; /** * @ORM\OneToMany(targetEntity="NewsImage", mappedBy="news") */ protected $image; /** * @ORM\OneToMany(targetEntity="Media", mappedBy="news") */ private $media; /** * @ORM\ManyToMany(targetEntity="News", inversedBy="relatedTo") * @ORM\JoinTable(name="news_to_news", * joinColumns={@ORM\JoinColumn(name="from_news_id", referencedColumnName="id")}, * inverseJoinColumns={@ORM\JoinColumn(name="to_news_id", referencedColumnName="id")} * ) */ private $relatedFrom; /** * @ORM\ManyToMany(targetEntity="News", mappedBy="relatedFrom") */ private $relatedTo; /** * @ORM\ManyToOne(targetEntity="Artist") * @ORM\JoinColumn(name="artist_id", referencedColumnName="id") */ private $artist; /** * @ORM\Column(type="boolean") */ private $public; /** * @ORM\Column(type="boolean", nullable=true) */ private $deleted; /** * Constructor */ public function __construct() { $this->newsArticle = new \Doctrine\Common\Collections\ArrayCollection(); $this->image = new \Doctrine\Common\Collections\ArrayCollection(); $this->media = new \Doctrine\Common\Collections\ArrayCollection(); $this->relatedFrom = new \Doctrine\Common\Collections\ArrayCollection(); $this->relatedTo = new \Doctrine\Common\Collections\ArrayCollection(); } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set ident * * @param string $ident * * @return News */ public function setIdent($ident) { $this->ident = $ident; return $this; } /** * Get ident * * @return string */ public function getIdent() { return $this->ident; } /** * Set validFrom * * @param \DateTime $validFrom * * @return News */ public function setValidFrom($validFrom) { $this->validFrom = $validFrom; return $this; } /** * Get validFrom * * @return \DateTime */ public function getValidFrom() { return $this->validFrom; } /** * Set validTo * * @param \DateTime $validTo * * @return News */ public function setValidTo($validTo) { $this->validTo = $validTo; return $this; } /** * Get validTo * * @return \DateTime */ public function getValidTo() { return $this->validTo; } /** * Set public * * @param boolean $public * * @return News */ public function setPublic($public) { $this->public = $public; return $this; } /** * Get public * * @return boolean */ public function getPublic() { return $this->public; } /** * Set deleted * * @param boolean $deleted * * @return News */ public function setDeleted($deleted) { $this->deleted = $deleted; return $this; } /** * Get deleted * * @return boolean */ public function getDeleted() { return $this->deleted; } /** * Add newsArticle * * @param \Acme\Bundle\Entity\NewsArticle $newsArticle * * @return News */ public function addNewsArticle(\Acme\Bundle\Entity\NewsArticle $newsArticle) { $this->newsArticle[] = $newsArticle; return $this; } /** * Remove newsArticle * * @param \Acme\Bundle\Entity\NewsArticle $newsArticle */ public function removeNewsArticle(\Acme\Bundle\Entity\NewsArticle $newsArticle) { $this->newsArticle->removeElement($newsArticle); } /** * Get newsArticle * * @return \Doctrine\Common\Collections\Collection */ public function getNewsArticle() { return $this->newsArticle; } /** * Add image * * @param \Acme\Bundle\Entity\NewsImage $image * * @return News */ public function addImage(\Acme\Bundle\Entity\NewsImage $image) { $this->image[] = $image; return $this; } /** * Remove image * * @param \Acme\Bundle\Entity\NewsImage $image */ public function removeImage(\Acme\Bundle\Entity\NewsImage $image) { $this->image->removeElement($image); } /** * Get image * * @return \Doctrine\Common\Collections\Collection */ public function getImage() { return $this->image; } /** * Add medium * * @param \Acme\Bundle\Entity\Media $medium * * @return News */ public function addMedia(\Acme\Bundle\Entity\Media $medium) { $this->media[] = $medium; return $this; } /** * Remove medium * * @param \Acme\Bundle\Entity\Media $medium */ public function removeMedia(\Acme\Bundle\Entity\Media $medium) { $this->media->removeElement($medium); } /** * Get media * * @return \Doctrine\Common\Collections\Collection */ public function getMedia() { return $this->media; } /** * Add relatedFrom * * @param \Acme\Bundle\Entity\News $relatedFrom * * @return News */ public function addRelatedFrom(\Acme\Bundle\Entity\News $relatedFrom) { $this->relatedFrom[] = $relatedFrom; return $this; } /** * Remove relatedFrom * * @param \Acme\Bundle\Entity\News $relatedFrom */ public function removeRelatedFrom(\Acme\Bundle\Entity\News $relatedFrom) { $this->relatedFrom->removeElement($relatedFrom); } /** * Get relatedFrom * * @return \Doctrine\Common\Collections\Collection */ public function getRelatedFrom() { return $this->relatedFrom; } /** * Add relatedTo * * @param \Acme\Bundle\Entity\News $relatedTo * * @return News */ public function addRelatedTo(\Acme\Bundle\Entity\News $relatedTo) { $this->relatedTo[] = $relatedTo; return $this; } /** * Remove relatedTo * * @param \Acme\Bundle\Entity\News $relatedTo */ public function removeRelatedTo(\Acme\Bundle\Entity\News $relatedTo) { $this->relatedTo->removeElement($relatedTo); } /** * Get relatedTo * * @return \Doctrine\Common\Collections\Collection */ public function getRelatedTo() { return $this->relatedTo; } /** * Set artist * * @param \Acme\Bundle\Entity\Artist $artist * * @return News */ public function setArtist(\Acme\Bundle\Entity\Artist $artist = null) { $this->artist = $artist; return $this; } /** * Get artist * * @return \Acme\Bundle\Entity\Artist */ public function getArtist() { return $this->artist; } } 实体:

NewsArticle

NewsType类(除外):

<?php

// src/Acme/Bundle/Entity/NewsArticle.php

namespace Acme\Bundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @ORM\Table(name="news_article")
 */
class NewsArticle {

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="News", inversedBy="newsArticle")
     * @ORM\JoinColumn(name="news_id", referencedColumnName="id")
     */
    private $news;

    /**
     * @ORM\Column(type="string", length=150, unique=false, nullable=false)
     * @Assert\NotBlank()
     */
    private $headline;

    /**
     * @ORM\Column(type="string", length=150, nullable=true)
     */
    private $subheadline;

    /**
     * @ORM\Column(type="string", length=65536, nullable=false)
     * @Assert\NotBlank()
     */
    private $bodytext;

    /**
     * @ORM\ManyToOne(targetEntity="Language")
     * @ORM\JoinColumn(name="language_id", referencedColumnName="id")
     */
    private $languageId;


    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set headline
     *
     * @param string $headline
     *
     * @return NewsArticle
     */
    public function setHeadline($headline)
    {
        $this->headline = $headline;

        return $this;
    }

    /**
     * Get headline
     *
     * @return string
     */
    public function getHeadline()
    {
        return $this->headline;
    }

    /**
     * Set subheadline
     *
     * @param string $subheadline
     *
     * @return NewsArticle
     */
    public function setSubheadline($subheadline)
    {
        $this->subheadline = $subheadline;

        return $this;
    }

    /**
     * Get subheadline
     *
     * @return string
     */
    public function getSubheadline()
    {
        return $this->subheadline;
    }

    /**
     * Set bodytext
     *
     * @param string $bodytext
     *
     * @return NewsArticle
     */
    public function setBodytext($bodytext)
    {
        $this->bodytext = $bodytext;

        return $this;
    }

    /**
     * Get bodytext
     *
     * @return string
     */
    public function getBodytext()
    {
        return $this->bodytext;
    }

    /**
     * Set news
     *
     * @param \Acme\Bundle\Entity\News $news
     *
     * @return NewsArticle
     */
    public function setNews(\Acme\Bundle\Entity\News $news = null)
    {
        $this->news = $news;

        return $this;
    }

    /**
     * Get news
     *
     * @return \Acme\Bundle\Entity\News
     */
    public function getNews()
    {
        return $this->news;
    }

    /**
     * Set languageId
     *
     * @param \Acme\Bundle\Entity\Language $languageId
     *
     * @return NewsArticle
     */
    public function setLanguageId(\Acme\Bundle\Entity\Language $languageId = null)
    {
        $this->languageId = $languageId;

        return $this;
    }

    /**
     * Get languageId
     *
     * @return \Acme\Bundle\Entity\Language
     */
    public function getLanguageId()
    {
        return $this->languageId;
    }

    public function __toString() {
        return $this->getHeadline();
    }
}

任何提示如何实现目标?我将不胜感激任何帮助!

编辑#1:

感谢Terenoth,我能够将包含默认class NewsType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder // [...] ->add('relatedTo', EntityType::class, array( 'class' => 'Bundle:News', 'choice_label' => function($news) { return $news->getNewsArticle(); }, 'multiple' => true, 'expanded' => false, 'required' => false )) // [...] ; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => 'Acme\Bundle\Entity\News', )); } } 对象的变量传递给Language类,并按照他的代码示例过滤具有默认语言的NewsType实体。 仅仅返回News属性(headline)失败,并显示以下错误消息:

  

尝试调用类“Doctrine \ Common \ Collections \ ArrayCollection”的名为“getHeadline”的未定义方法。

新的NewsType类(除了):

return $newsArticle->getHeadline();

如何获取class NewsType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $searchedLanguage = $options['languageId']; $builder ->add('relatedTo', EntityType::class, array( 'class' => 'Bundle:News', 'query_builder' => function (EntityRepository $er) { return $er->createQueryBuilder('a') ->where('a.deleted = 0') ->orderBy('a.validFrom', 'ASC'); }, 'choice_label' => function($relatedTo, $searchedLanguage) { $newsArticle = $relatedTo ->getNewsArticle() ->filter( function(NewsArticle $newsArticle) use ($searchedLanguage) { return $newsArticle->getLanguageId() === $searchedLanguage; } ) ; return $newsArticle->getHeadline(); }, 'multiple' => true, 'expanded' => false, 'required' => false )) ; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => 'Acme\Bundle\Entity\News', 'languageId' => 'Acme\Bundle\Entity\Language', )); } } 实体而不是ArrayCollection?

提前感谢!

1 个答案:

答案 0 :(得分:0)

您定义地图的方式,$newsArticles中的News是OneToMany关系,这意味着每个NewsArticles有多个News。很明显,getNewsArticles会返回Collection的{​​{1}}。

要么你的地图定义错误,新闻应该只有1个NewsArticle,所以用NewsArticles替换你的OneToMany ... 您应该选择几个OneToOne来显示其标题。

编辑:根据您在评论中的指示,您应该做什么(假设您在变量中有$ searchingLanguage)。

NewsArticle