2016-06-10 248 views
0

我被stucked爲建設一個形式Symfony的3Symfony的形式:一對多和CollectionType場

我定義的「新聞」包含的屬性「newsArticle」,其中有一個一對多關係的實體「NewsArticle」實體,持有屬性'標題','subheader和'bodytext'的翻譯。 目標是提供一種形式,一方面爲'新聞'的屬性保留字段,另一方面爲默認語言創建'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(); 
    } 
} 

實體NewsArticle(節選):

/** 
* @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()」存在並且在Bundle中的類「Symfony \ Component \ Form \ FormView」中具有公共訪問權限:_Partials:Form/news.ht ml.twig第27行

...並不知道如何訪問相關實體的屬性?任何提示?

編輯#1:

完整的「Child'實體包括getter/setter方法:

/** 
* @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存在,但我不知道爲什麼錯誤信息缺失方法得到h eadline()而不是得到H eadline()?難道是,問題是TWIG中的語法錯誤:{{form_errors(form.headline)}}?我也嘗試過{{form_errors(form.newsArticle.headline)}},但錯誤信息保持不變。

有什麼提示嗎?

+0

閱讀一下關於私有/受保護和公共屬性的內容:http://php.net/manual/en/language.oop5.visibility.php。一旦你明白了,getter/setter的需求就會變得明顯。也可能想看看Symfony文檔。大量使用實體和表單的例子。 – Cerad

+0

即使我將子實體NewsArticle的所有屬性設置爲public,我也會得到相同的錯誤消息。我讀過Symfony Docs,特別是關於FormTypes的章節,但不幸的是沒有這種嵌套表單的例子。它只提到CollectionType可以完成這項工作:「在更復雜的示例中,可以嵌入整個表單,這在創建公開一對多關係的表單時非常有用」(https://symfony.com/doc /current/reference/forms/types/collection.html) – Pixelrocker

+0

您是否閱讀過食譜? http://symfony.com/doc/current/cookbook/form/form_collections.html – Cerad

回答

0

我認爲這個問題只是設定裝置干將

正如你試試這個命令:

php bin/console doctrine:generate:entities youBundle 

用於生成的getter/setter或寫

而你在你的實體忘記inversedBy NewsActicle

是這樣的:

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

對,我正在使用控制檯命令doctrine:generate:生成getters和setters的實體。感謝提示添加'inversedBy' - 不幸的是錯誤信息仍然存在:(我會發布getters/setters,希望你的猜測指向正確的方向。 – Pixelrocker

0

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

的一個問題是,$ 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 %} 

另一個重要變化是,以實例化NewsArticle對象首先在NewsController:

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

我不覺得這是最好的解決辦法(迭代格外一個數組,只有一個對象),但至少我不得到錯誤信息,並似乎工作爲此時此刻。 如果你有改進的想法,請讓我知道 - 我會很感激你的幫助!