没有预加载的 Symfony 表单 EntityType
Symfony form EntityType without preloading
有没有办法在 Symfony 中获得一个 EntityType
表单元素,它不会预加载所有条目,但仍然接受它们?
背景:这是一个图像选择器,可能会存储 1000 多张图像。每次呈现字段时,我不想给数据库带来负载。该表单有一个自定义前端,使用隐藏字段和 Javascript(加载分页图像列表)。
当前的实现工作正常,但因为它扩展了 EntityType
它会进行所有预加载,而当使用 ChoiceType
时,表单不接受值(除非,你给他们作为选择,这意味着从数据库中加载所有条目)
------------------------编辑-------------------- --
我正在使用建议的 bundle。如果你觉得需要像我一样拥有自己的视图(小部件),你可以很容易地实现它:
如果你使用composer,你可以简单地安装所有需要的文件运行
composer require alsatian/form-bundle dev-master
安装捆绑包后,您可以按照以下步骤操作:
首先,您必须创建自己的表单域(我的看起来像这样):
<?php
namespace AppBundle\Form\Fields;
use Symfony\Component\Form\AbstractType;
use Alsatian\FormBundle\Form\ExtensibleEntityType;
class UploadFileType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function getParent() {
return ExtensibleEntityType::class;
}
/**
* {@inheritdoc}
*/
public function getName() {
return 'app_upload_file';
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'app_upload_file';
}
}
注意:你可以在getBlockPrefix
中放任何你喜欢的东西,只要记住你放在那里的东西即可。
接下来您需要修改表单主题(doc)并添加您自己的小部件:
{%- block app_upload_file_widget -%}
{{ dump(form) }}{# output some debug info #}
{% if not expanded %}
{# example for some fake entries #}
{% if multiple %}
<input type="hidden" name="{{ full_name }}" value="1" />
<input type="hidden" name="{{ full_name }}" value="2" />
<input type="hidden" name="{{ full_name }}" value="3" />
{% else %}
<input type="hidden" name="{{ full_name }}" value="1" />
{% endif %}
{% else %}
{{- block('choice_widget') -}}
{% endif %}
{%- endblock app_upload_file_widget -%}
注意:这里我们需要我们的getBlockPrefix
,只需在其中添加一个_widget
即可!
最后,我们可以将它添加到我们的一个表单中:
<?php
namespace AppBundle\Form\Admin;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CompanyType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('logo', \AppBundle\Form\Fields\UploadFileType::class, array(
'class' => \AppBundle\Entity\File::class,
'choice_label' => 'originalName',
))
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Company'
));
}
}
当然我们需要在我们的实体中有一个连接,对我来说,它看起来像这样:
/**
* @ORM\ManyToOne(targetEntity="File")
* @ORM\JoinColumn(name="logo_id", referencedColumnName="id")
*/
private $logo;
我希望,这对和我情况相同的人有帮助(:
这个问题每 3 天出现一次:)
我从 :
粘贴我的答案
我写了一个包 (Alsatian/FormBundle),它在服务器端做你想做的事。
How to avoid loading each entities by each form rendering :
abstract class AbstractExtensibleChoicesType extends AbstractRoutableType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('choices',array());
}
}
在 Form::PRE_SUBMIT 事件中获取提交的选项(如果您使用表单进行编辑,也 PRE_SET_DATA),并将这些选项重新注入字段。
有没有办法在 Symfony 中获得一个 EntityType
表单元素,它不会预加载所有条目,但仍然接受它们?
背景:这是一个图像选择器,可能会存储 1000 多张图像。每次呈现字段时,我不想给数据库带来负载。该表单有一个自定义前端,使用隐藏字段和 Javascript(加载分页图像列表)。
当前的实现工作正常,但因为它扩展了 EntityType
它会进行所有预加载,而当使用 ChoiceType
时,表单不接受值(除非,你给他们作为选择,这意味着从数据库中加载所有条目)
------------------------编辑-------------------- --
我正在使用建议的 bundle。如果你觉得需要像我一样拥有自己的视图(小部件),你可以很容易地实现它:
如果你使用composer,你可以简单地安装所有需要的文件运行
composer require alsatian/form-bundle dev-master
安装捆绑包后,您可以按照以下步骤操作:
首先,您必须创建自己的表单域(我的看起来像这样):
<?php
namespace AppBundle\Form\Fields;
use Symfony\Component\Form\AbstractType;
use Alsatian\FormBundle\Form\ExtensibleEntityType;
class UploadFileType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function getParent() {
return ExtensibleEntityType::class;
}
/**
* {@inheritdoc}
*/
public function getName() {
return 'app_upload_file';
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'app_upload_file';
}
}
注意:你可以在getBlockPrefix
中放任何你喜欢的东西,只要记住你放在那里的东西即可。
接下来您需要修改表单主题(doc)并添加您自己的小部件:
{%- block app_upload_file_widget -%}
{{ dump(form) }}{# output some debug info #}
{% if not expanded %}
{# example for some fake entries #}
{% if multiple %}
<input type="hidden" name="{{ full_name }}" value="1" />
<input type="hidden" name="{{ full_name }}" value="2" />
<input type="hidden" name="{{ full_name }}" value="3" />
{% else %}
<input type="hidden" name="{{ full_name }}" value="1" />
{% endif %}
{% else %}
{{- block('choice_widget') -}}
{% endif %}
{%- endblock app_upload_file_widget -%}
注意:这里我们需要我们的getBlockPrefix
,只需在其中添加一个_widget
即可!
最后,我们可以将它添加到我们的一个表单中:
<?php
namespace AppBundle\Form\Admin;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CompanyType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('logo', \AppBundle\Form\Fields\UploadFileType::class, array(
'class' => \AppBundle\Entity\File::class,
'choice_label' => 'originalName',
))
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Company'
));
}
}
当然我们需要在我们的实体中有一个连接,对我来说,它看起来像这样:
/**
* @ORM\ManyToOne(targetEntity="File")
* @ORM\JoinColumn(name="logo_id", referencedColumnName="id")
*/
private $logo;
我希望,这对和我情况相同的人有帮助(:
这个问题每 3 天出现一次:)
我从
我写了一个包 (Alsatian/FormBundle),它在服务器端做你想做的事。
How to avoid loading each entities by each form rendering :
abstract class AbstractExtensibleChoicesType extends AbstractRoutableType { public function configureOptions(OptionsResolver $resolver) { $resolver->setDefault('choices',array()); } }
在 Form::PRE_SUBMIT 事件中获取提交的选项(如果您使用表单进行编辑,也 PRE_SET_DATA),并将这些选项重新注入字段。