当我手工编写大部分代码时,我有一个由可变数量的div元素组成的表单,我在提交时通过post将其作为数组处理,但我无法为我的生活弄清楚如何在Symfony中做类似的事情,我开始感到非常沮丧。下面是一个对象的模板类的原始实现(使用我自己的简单模板引擎):
<div class="img_transfer">
<img class="toggle" src="{{src}}">
<input class="title" type="text" name="title[{{i}}]" placeholder="Title"><br>
Upload to Sta.sh:
<input type="radio" name="stash[{{i}}]" value="0" checked="checked"> No
<input type="radio" name="stash[{{i}}]" value="1"> Yes<br>
Showcase:
<input type="radio" name="showcase[{{i}}]" value="0" checked="checked"> No
<input type="radio" name="showcase[{{i}}]" value="1"> Yes<br>
<input class="save" type="hidden" name="save[{{i}}]" value="0">
<input type="hidden" name="old_path[{{i}}]" value="{{old_path}}">
</div>
{{i}}
是循环迭代的占位符,这工作得很好,但这是我如何在Symfony中尝试做到的:
$img_tmp = glob('img_tmp/*.*');
$data = array();
foreach ($img_tmp as $src) {
//$inter = end();
$parts = explode('/', $src);
$file = end($parts);
//$name = explode($inter)[0];
$name = explode('.', $file)[0];
$data[$name] = new Art();
}
$builder = $this->createFormBuilder($data);
foreach ($data as $key => $value) {
//$builder->add($key, (new ArtType())->setSrc($key));
$builder->add($key, ArtType::class, array('img_src' => $key));
}
$form = $builder->getForm();
return $this->render('img_transfer.html.twig', array('form' => $form->createView()));
这主要是基于另一个关于如何拥有对象形式的建议,但它不会让我将自定义选项发送到要构建的表单,我认为这可能是我最后的障碍,让这个做我很容易实现的手工。我非常欢迎大家的建议,我更喜欢一种不那么黑客的方式来做这件事,我也很想知道我是否只是忽略了一种简单的方法,或者这是否像我认为的那样可怕地不直观。当我有时间的时候,我会编辑和重组这个问题,使它成为一个更好的问题。
Edit:格式和以下附加信息:应用程序的这个特殊部分应该取任意名称和扩展名转储在"web/img_tmp"目录中的图像,并将它们移动到"web/img"目录中,同时使用PHP的uniqid()重命名它们并将它们输入数据库;我想要为每个"/img_tmp/"生成一组字段。"允许我在将它们持久化到DB之前为每个属性设置属性。我找到的所有关于如何同时提交多个对象的资源要么不完整,要么过于复杂。
结果是,我正在寻找涉及弃用代码的解决方案,即我自定义类型的setDefaultOptions(OptionsResolverInterface $resolver)
方法,它显然在Symfony 3.0中被删除了。作为参考,以下是如何在表单中提交多个对象并向传递自定义选项的完整代码:
public function someAction()
{
$vals = array('customVal1', 'customVal2', 'customVal3');
foreach ($vals as $v) {
$data[$v] = new YourObject();
}
$builder = $this->createFormBuilder($data);
//I put this here so I don't have to scroll all the way to the bottom to submit;
//this will render it at the top by default (at least on mine)
$builder->add('submit', SubmitType::class, array('label' => 'Submit'));
foreach ($vals as $v) {
$builder->add($v, YourObjectType::class, array(
'custom_val' => $v
));
}
$form = $builder->getForm();
return $this->render('the_page.html.twig', array('form' => $form->createView()));
}
定制表单模板
{% block yourobject_widget %}
<div>
<img src="{{ custom_val }}"> //This is set by the call to setAttribute() in YourObjectType
{% for child in form %}
{{ form_row(child) }}
{% endfor %}
</div>
{% endblock %}
app/config/config.yml
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
form_themes:
- 'form/fields.html.twig'
最后,YourObjectType
namespace AppBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'Extension'Core'Type'TextType;
use Symfony'Component'Form'Extension'Core'Type'ChoiceType;
use Symfony'Component'Form'Extension'Core'Type'CollectionType;
use Symfony'Component'Form'Extension'Core'Type'HiddenType;
use Symfony'Component'Form'Extension'Core'Type'SubmitType;
use Symfony'Component'Form'FormView;
use Symfony'Component'Form'FormInterface;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolver;
class YourObjectType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults(array(
'data_class' => 'AppBundle'Entity'YourObject',
'custom_val' => '' //This is important. You have to set defaults for
//options for Symfony to allow you to pass them
));
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['custom_val'] = $options['custom_val'];
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('some_text_field', TextType::class)
->add('some_choice_field', ChoiceType::class, array(
'choices' => array('Yes' => true, 'No' => false),
'expanded' => true
))
->add('some_hidden_field', HiddenType::class, array('mapped' => false))
->setAttribute('custom_val', $options['custom_val']);
}
}