使用单表继承构建表单
我有我的实体文章和一个像这样的单表继承:
/*** 文章** @ORMTable(name="文章")* @ORMEntity(repositoryClass="PMPlatformBundleRepositoryArticleRepository")* @ORMInheritanceType("SINGLE_TABLE")* @ORMDiscriminatorColumn(name="media", type="string")* @ORMDiscriminatorMap({"article" = "Article", "movie" = "Movie", "image" = "Image", "text" = "Text"})*/类文章{受保护的 $id;受保护的 $title;受保护的 $ 说明;受保护的 $author;//其他属性和setter getter}类图像扩展文章{私人 $path;//getter setter}类电影扩展文章{私人 $url;//getter setter}
所以我的文章的对象类型是图像或电影或仅文本.好的,现在我想构建一个表单,用户可以在其中发布新文章:在这种表单中,用户必须在树类型(3 个单选按钮):图像或电影或文本之间进行选择,当然还有其他字段:标题和描述.我怎么能这样做?因为用命令
<块引用>php bin/console 原则:generate:form myBundle:Article
呈现的表单是:
class ArticleType 扩展 AbstractType{/*** @param FormBuilderInterface $builder* @param 数组 $options*/公共函数 buildForm(FormBuilderInterface $builder, array $options){$builder->add('title', TextType::class)->add('description', TextareaType::class)->add('save', SubmitType::class);;}/*** @param OptionsResolver $resolver*/公共函数 configureOptions(OptionsResolver $resolver){$resolver->setDefaults(array('data_class' =>'PMPlatformBundleEntityArticle'));}}
我不知道如何以这种形式实现我的 STI 关系.因为我的文章实体/对象中没有该类型的字段(仅在我的表中).我必须添加一个 Custom ChoiceType() 字段,但它需要一个属性.当我尝试在表单中添加它时:
<块引用> ->add('path', SearchType::class)->add('url', UrlType::class)
我收到此错误:
属性path"和方法getPath()"、path()"、isPath()"、hasPath()"、__get()"都不存在并且在类中具有公共访问权限PMPlatformBundleEntityArticle".
因为我创建了一个文章的实例,而不是一个图像或电影的实例.最初我创建了一个 STI,认为一个新的文章实例也允许我定义文章的类型".但不是 ?对吗?
解决方案你必须制作三种形式(一种用于Article
,一种用于Movie
,一种用于对于 Image
).然后,在您的控制器中,您必须选择处理它们:
- 您可以使用一个操作来处理这三个表单(您可以使用
$form->isSubmitted()
检查哪个提交了) - 您按表单创建一个操作,然后设置表单操作 URL将每个表单发送到正确的控制器.
最后,在您的模板中,您将表单封装在一个 div 中,并使用我上一篇文章中的示例.
{% 扩展 "CoreBundle::layout.html.twig" %}{% 区块标题 %}{{ parent() }}{% endblock %}{% 阻止 btn_scrollspy %}{% 结束块 %}{% 块 bundle_body %}<div class="well"><div class="选择器"><input type="radio" name="form-selector" value="article-form">文章<input type="radio" name="form-selector" value="movie-form">电影<input type="radio" name="form-selector" value="image-form">图片<div class="form article-form" style="display: none;">{{ 表单(文章表单)}}
<div class="form movie-form" style="display: none;">{{ 形式(电影形式)}}
<div class="form image-form" style="display: none;">{{ 表单(图像表单)}}
{% 结束块 %}
I have my entity Article and one single table inheritance like this :
/**
* Article
*
* @ORMTable(name="article")
* @ORMEntity(repositoryClass="PMPlatformBundleRepositoryArticleRepository")
* @ORMInheritanceType("SINGLE_TABLE")
* @ORMDiscriminatorColumn(name="media", type="string")
* @ORMDiscriminatorMap({"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
}
So my article's object type is either Image or movie or text only. Ok now I would like build a form wherein users can post a new article : in this form, the user has to choice between tree type (3 radios button) : image OR movie OR text only and of course the other fields : title and description. How I can do that ? Because with the command
php bin/console doctrine:generate:form myBundle:Article
The form rendered is :
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' => 'PMPlatformBundleEntityArticle'
));
}
}
I don't know the way to implement my STI relation in this form. Because I have not field in my Article entity/object for the type (only in my table). I have to add a Custom ChoiceType() field but it require a attribute. When I try to add this in the form :
->add('path', SearchType::class) ->add('url', UrlType::class)
I got this error :
Neither the property "path" nor one of the methods "getPath()", "path()", "isPath()", "hasPath()", "__get()" exist and have public access in class "PMPlatformBundleEntityArticle".
Because I have create an instance of Article, not an instance of Image or Movie. Initially I created a STI thinking a new instance of Article would allow me also to define the "type" of article. But not ? Right ?
解决方案You will have to make three forms (one for an Article
, one for a Movie
and one for an Image
). Then, in your controller, you have to options to deal with them:
- Either you use one action to handle the three forms (you can check wich one is submitted by using
$form->isSubmitted()
) - You create one action by form, and set the form action URL for each form to the correct controller.
Finally, in your template, you encapsulate your forms in a div, and use the example in my previous post.
{% 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 %}
相关文章