Symfony表单:OneToMany和CollectionType字段

时间:2016-06-10 23:58:55

标签: php doctrine symfony

我开始使用Symfony 3构建一个表单。

我定义了一个包含属性'newsArticle'的实体'News',它与实体'NewsArticle'有一个OneToMany关系,持有其属性'headline','subheader和'bodytext'的翻译。 目标是提供一个表单,该表单一方面保存“新闻”属性的字段,另一方面提供字段,以创建默认语言的“新闻文章”条目。

实体新闻(摘录):

/**
 * @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"})
     */
    private $newsArticle;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->newsArticle = new \Doctrine\Common\Collections\ArrayCollection();
    }
}

实体新闻(摘录):

/**
 * @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")
     * @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;
}

控制器(摘录):

public function addAction(Request $request) {
    $lang = $this->getDoctrine()
        ->getRepository('Bundle:Language')
        ->findOneBy(array('deleted' => 0, 'fallback' => 1));

    $news = new News();
    //$news->newsArticle->setLanguageId($lang);

    $form = $this->createForm(NewsType::class, $news);

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $em = $this->getDoctrine()->getManager();
        $em->persist($news);
        $em->flush();
    }

    return $this->render('Bundle:News:add.html.twig', array(
        'form' => $form->createView(),
        'news' => $news,
    ));
}

TWIG模板(摘录):

{{ form_start(form) }}
    <div class="form-group">
        {{ form_label(form.headline) }}
        <div class="col-sm-8 col-md-6">
            {{ form_errors(form.headline) }}
            {{ form_widget(form.headline) }}
        </div>
    </div>
    <div class="form-group">
        {{ form_label(form.subheadline) }}
        <div class="col-sm-8 col-md-6">
            {{ form_errors(form.subheadline) }}
            {{ form_widget(form.subheadline) }}
        </div>
    </div>
    <div class="form-group">
        {{ form_label(form.bodytext) }}
        <div class="col-sm-8 col-md-6">
            {{ form_errors(form.bodytext) }}
            {{ form_widget(form.bodytext) }}
        </div>
    </div>
{{ form_end(form) }}

NewsType(摘录):

class NewsType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('newsArticle', CollectionType::class, array(
                'entry_type'   => NewsArticleType::class,
                'allow_add'   => true,
                'allow_delete'   => true,
            ))
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'Bundle\Entity\News',
        ));
    }
}

NewsArticleType(摘录):

class NewsArticleType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('headline', TextType::class, array(
                'required' => false,
            ))
            ->add('subheadline', TextType::class, array(
                'required' => false,
            ))
            ->add('bodytext', CKEditorType::class, array(
                'required' => false,
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'Bundle\Entity\NewsArticle',
        ));
    }
}

不幸的是我收到了错误消息......

  

属性“标题”和“headline()”,“getheadline()”/“isheadline()”或“__call()”方法之一都不存在,并且在“Symfony \ Component \ Form”类中具有公共访问权限\ FormView“in Bundle:_Partials:Form / news.html.twig at the line 27

......并且不知道如何访问相关实体的属性?任何提示?

编辑#1:

完整的'儿童'实体,包括吸气剂/孵化器:

/**
 * @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 \Bundle\Entity\News $news
     *
     * @return NewsArticle
     */
    public function setNews(\Bundle\Entity\News $news = null)
    {
        $this->news = $news;

        return $this;
    }

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

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

        return $this;
    }

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

属性的getter和setter存在,但我想知道为什么错误消息错过了方法 get h eadline()而不是 get ħ eadline()?可能是,问题是TWIG中的错误语法:{{form_errors(form.headline)}}?我也尝试了{{form_errors(form.newsArticle.headline)}},但错误信息仍然相同。

请提供任何提示?

2 个答案:

答案 0 :(得分:0)

我认为这个问题只是设定了吸气剂

尝试此命令时:

php bin/console doctrine:generate:entities youBundle

用于生成getter / setter或写入

你在实体NewsActicle

中忘记了inversedBy 像这样:

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

答案 1 :(得分:0)

毕竟我取得了一些进展并摆脱了恐怖信息。

我的TWIG中的一个问题是 $ newsArticle 是一个对象数组而不是一个对象,所以我需要首先迭代数组:

{% for newsArticle in form.newsArticle %}
<div class="form-group">
    {{ form_label(newsArticle.headline) }}
    <div class="col-sm-8 col-md-6">
        {{ form_errors(newsArticle.headline) }}
        {{ form_widget(newsArticle.headline) }}
    </div>
</div>
<div class="form-group">
    {{ form_label(newsArticle.subheadline) }}
    <div class="col-sm-8 col-md-6">
        {{ form_errors(newsArticle.subheadline) }}
        {{ form_widget(newsArticle.subheadline) }}
    </div>
</div>
<div class="form-group">
    {{ form_label(newsArticle.bodytext) }}
    <div class="col-sm-8 col-md-6">
        {{ form_errors(newsArticle.bodytext) }}
        {{ form_widget(newsArticle.bodytext) }}
    </div>
</div>
{% endfor %}

另一个重要的变化是首先在NewsController中实例化NewsArticle对象:

public function addAction(Request $request) {
    $lang = $this->getDoctrine()
        ->getRepository('Bundle:Language')
        ->findOneBy(array('deleted' => 0, 'fallback' => 1));

    $article = new NewsArticle();
    $article->setLanguageId($lang);

    $news = new News();
    $news->setPublic(0);
    $news->setDeleted(0);
    $news->setIdent($hash);
    $news->getNewsArticle()->add($article);


    $form = $this->createForm(NewsType::class, $news);

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $em = $this->getDoctrine()->getManager();
        $em->persist($news);
        $em->flush();

        $this->addFlash(
            'success',
            'Your changes were saved!'
        );
    }

    return $this->render('Bundle:News:add.html.twig', array(
        'form' => $form->createView(),
        'news' => $news,
    ));
}

我不认为这是最好的解决方案(特别是迭代一个只有一个对象的数组),但至少我没有得到错误信息,它似乎暂时有效。 如果您有改进的想法,请告诉我 - 我非常感谢您的帮助!