簡體   English   中英

Symfony表單:OneToMany和CollectionType字段

[英]Symfony Form: OneToMany and CollectionType Field

我被困於用Symfony 3構建表單。

我定義了一個實體“新聞”,其中包含一個屬性“ newsArticle”,該實體與實體“ NewsArticle”具有一個一對多關系,其中包含其屬性“標題”,“副標題”和“正文”的翻譯。 目的是提供一種表單,該表單一方面保留“新聞”屬性的字段,另一方面保留用於為默認語言創建“新聞文章”條目的表單。

實體新聞(節選):

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

新聞類型(節選):

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”或方法“ headline()”,“ getheadline()” /“ isheadline()”或“ __call()”都不存在,並且在類“ Symfony \\ Component \\ Form \\ FormView”中沒有公共訪問權限在第27行的Bundle:_Partials:Form / news.html.twig中

...而且不知道如何訪問相關實體的屬性? 有什么提示嗎?

編輯#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;
    }
}

存在屬性的獲取器和設置器,但是我想知道為什么錯誤消息會錯過方法get h eadline()而不是get H eadline()嗎? 可能是問題出在TWIG中的語法錯誤:{{form_errors(form.headline)}}嗎? 我也嘗試過{{form_errors(form.newsArticle.headline)}},但錯誤消息仍然相同。

有什么提示嗎?

我認為問題只是使吸氣者受阻

當您嘗試此命令時:

php bin/console doctrine:generate:entities youBundle

用於生成getter / setter或編寫它

而且您忘記了實體中的逆數

像這樣 :

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

畢竟,我取得了一些進展,擺脫了錯誤信息。

我的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,
    ));
}

我認為這不是最好的解決方案(特別是迭代僅包含一個對象的數組),但至少我沒有收到錯誤消息,並且它似乎暫時可行。 如果您有改進的想法,請告訴我-非常感謝您的幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM