2016-09-30 91 views
1

构建表我有我的实体文章和一个单表继承这样的:与单表继承

/** 
* Article 
* 
* @ORM\Table(name="article") 
* @ORM\Entity(repositoryClass="PM\PlatformBundle\Repository\ArticleRepository") 
* @ORM\InheritanceType("SINGLE_TABLE") 
* @ORM\DiscriminatorColumn(name="media", type="string") 
* @ORM\DiscriminatorMap({"article" = "Article", "movie" = "Movie", "image" = "Image", "text" = "Text"}) 
*/ 
class Article 
{ 
    protected $id; 
    protected $title; 
    protected $description; 
    protected $author; 
    //other attributes and setters getters 
} 

class Image extends Article 
{ 
    private $path; 
    //getter setter 
} 

class Movie extends Article 
{ 
    private $url; 
    //getter setter 
} 

所以我的文章的对象类型为图片或仅电影或文字。好吧,现在我想建立一个表单,用户可以发表一篇新文章:在这种形式下,用户必须选择树型(3无线电按钮):图像或电影或文本,当然还有其他字段:标题和描述。我该怎么做?因为用命令

PHP斌/控制台学说:生成:形式myBundle:文章

呈现的形式是:

class ArticleType extends AbstractType 
{ 
    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('title',   TextType::class) 
      ->add('description', TextareaType::class) 
      ->add('save',   SubmitType::class); 
     ; 
    } 

    /** 
    * @param OptionsResolver $resolver 
    */ 
    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'PM\PlatformBundle\Entity\Article' 
     )); 
    } 
} 

我不知道该实施方式我STI关系在这种形式。因为我的文章实体/对象中没有字段(仅在我的表格中)。 我必须添加一个Custom ChoiceType()字段,但它需要一个属性。 当我尝试的形式补充一点:

 ->add('path',   SearchType::class) 
     ->add('url',   UrlType::class) 

我得到这个错误:

无论属性“路径”,也不是方法之一“的getPath()”,“路径()“,”isPath()“,”hasPath()“,”__get()“并且在”PM \ PlatformBundle \ Entity \ Article“类中具有公共访问权限。

因为我创建了Article的实例,而不是Image或Movie的实例。最初,我创建了一个STI,认为一个新的文章实例可以让我定义文章的“类型”。但不是 ?对 ?

+2

为不应映射到底层对象属性(Article)的表单域添加'mapped:false'选项。那么你将不得不找到一种方法来正确处理这种形式。 –

+0

嗯,我不知道是否使用映射是一个好主意:false。我应该怎么做才能正确恢复路径和URL,因为它们确实存在于我的数据库和对象中(但通过继承)? –

+0

但是你没有'Image' /'Movie'对象,是吗?不,你没有。所以你认为它应该如何工作(不必介意是否可能)? –

回答

1

你将不得不作出三种形式(一个为Article,一个为Movie和一个为Image)。然后,在你的控制器,你必须选择来对付他们:

  • 要么你使用一个动作来处理三种形式(您可以检查至极一个是通过使用$form->isSubmitted()提交)
  • 您创建一个动作通过形式,并且set the form action URL为每个形式正确的控制器。

最后,在您的模板中,您将表单封装在一个div中,并在我以前的文章中使用该示例。

{% extends "CoreBundle::layout.html.twig" %} 

{% block title %}{{ parent() }}{% endblock %} 

{% block btn_scrollspy %} 
{% endblock %} 


{% block bundle_body %} 
    <div class="well"> 
     <div class="selector"> 
      <input type="radio" name="form-selector" value="article-form"> Article 
      <input type="radio" name="form-selector" value="movie-form"> Movie 
      <input type="radio" name="form-selector" value="image-form"> Image 
     </div> 

     <div class="form article-form" style="display: none;"> 
      {{ form(articleForm) }} 
     </div> 
     <div class="form movie-form" style="display: none;"> 
      {{ form(movieForm) }} 
     </div> 
     <div class="form image-form" style="display: none;"> 
      {{ form(imageForm) }} 
     </div> 
    </div> 
{% endblock %} 
+0

你能否更加详细地向我解释一下“如何做一个表单动作,并将每个表单的表单动作URL设置为正确的控制器。” ?因为我建立了3种形式,就像你说的那样,并使用引导Toggelable选项来查看(替换你的JS代码来隐藏/显示正确的形式)。它工作的很好,但我不能制作系统:一种形式的动作,因为一开始我有一个控制器为一个视图的一条路线,现在我有三个动作为三个路线的一个视图。 –

+0

在我的回答中的链接中解释了如何为表单定义动作(=>将在您提交表单时调用的URL)。所以在你的表格中,你只需要设置匹配正确控制器的路线。 – Boulzy

+0

是的,我已经做到了。看看我的新答案。 –

1

我同意评论中的dragoste:你不能指望表单自己推导出你想要基于一个值实例化的类的类型。

粗略地说,ImageMovie是相同的类型Article,而是一个Article不是Image和/或Movie

您必须手动检查。您可以像在注释中解释的那样在服务器端执行操作,字段使用mapped: false来确定您需要实例化的实体的类型,或者使用三种形式确定客户端与JavaScript(一个用于电影,一个用于文章,一个用于一个图像),并根据您的单选按钮显示正确的一个。


编辑:如何在JS中显示正确的窗体?

我创建了一个的jsfiddle来告诉你如何做到这一点使用jQuery:https://jsfiddle.net/61gc6v16/

随着jQuery的文档,你应该能够很快明白这是什么样做的,以使其适应您的需求。 :)

+0

好的,谢谢你的解释!我想用javascript构建这个表单系统。但我没有关于JS或Jquery的知识。它需要很多JS代码? –

+0

我编辑了我的答案。 :) JavaScript是增强用户体验的好方法,同时,它可以防止您在处理服务器端的事情时遇到一些麻烦。你应该看看它,因为它现在对于web开发人员来说几乎是不可或缺的,无论是前面还是后面。 jQuery是抓住语言背后的逻辑的好开始,因为它很容易学习,并且具有很好的功能。不过,请记住,了解jQuery并不了解JavaScript,并且有更多的框架可以为您提供更多更美妙的东西。 :) – Boulzy

+0

我回答给你看我的代码。 –

0

@Boulzy我这样做,它的工作原理:(。我在模板直接覆盖行动POST方法)

class ArticleController extends Controller 
    { 
     public function addAction(Request $request) 
     { 
      $form1 = $this->get('form.factory')->create(TextOnlyType::class); 
      $form2 = $this->get('form.factory')->create(ImageType::class); 
      $form3 = $this->get('form.factory')->create(MovieType::class); 
      return $this->render('PMPlatformBundle:Article:add.html.twig', array(
       'ArticleTextform' => $form1->createView(), 
       'ArticleImageform' => $form2->createView(), 
       'ArticleMovieform' => $form3->createView(), 
      )); 
     } 

     public function addArticleTextAction(Request $request) 
     { 
      $ArticleText = new TextOnly; 
      $form = $this->get('form.factory')->create(TextOnlyType::class, $ArticleText); 
      if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) { 
       $ArticleText->setAuthor(5); 
       $ArticleText->setLikes(0); 
       $em = $this->getDoctrine()->getManager(); 
       $em->persist($ArticleText); 
       $em->flush(); 

       $request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.'); 

       $listComments = $ArticleText->getComments(); 
       return $this->render('PMPlatformBundle:Article:view.html.twig', array(
        'article' => $ArticleText, 
        'listComments' => $listComments 
       )); 
      } 
      return $this->render('PMPlatformBundle:Article:add.html.twig', array(
       'form' => $form->createView(), 
      )); 
     } 

     public function addArticleImageAction(Request $request) 
     { 
      //the same system as TextOnly 
     } 

     public function addArticleMovieAction(Request $request) 
     { 
      //the same system as TextOnly 
     } 
} 

的addAction是我的位指示这是由路线显示被叫三种形式的看法。正如你可以看到这个代码工作,只要在提交的表单上没有错误。因为在这种情况下(当提交表单时发生错误),每个控制器需要返回3个表单的初始视图。我该怎么做?

+1

查看这些文档,选择一个看起来最感兴趣的文档:http://symfony.com/doc/current/controller/forwarding.html,https://symfony.com/doc/current/controller的.html#重定向。我很高兴能够提供帮助,但是您知道我不打算编写您的整个网站,对吧?我的意思是,尝试,失败,再试一次,犯错误并坚持不懈是学习过程中不可分割的一部分。你应该尝试更多的解决方案,在这里寻求帮助之前做更多的研究。你将通过这种方式更好,更快地学习。 – Boulzy