如何以Symfony形式创建和呈现对象数组

时间:2016-09-26 20:56:47

标签: php forms symfony-forms

当我手工完成大部分代码时,我有一个由可变数量的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()));

这主要是基于关于如何使用某种形式的对象的SO的另一个建议,但因为它不会让我将自定义选项发送到要构建的表单,我认为这可能是我获取的最后一个障碍这要做我手工实施的事情。我完全欢迎提出建议,并希望采用不那么黑客的方式来做这件事,并且也想知道我是否只是忽略了这样做的简单方法,或者是否这样做非常糟糕。直觉,因为我认为它是。当我有时间时,我会编辑并重新构建这个更好的问题。

修改:格式化以及以下附加信息: 应用程序的这个特定部分应该采用转储在&#34; web / img_tmp&#34;中的任意名称和扩展名的图像。目录,并将它们移动到&#34; web / img&#34;目录,同时用PHP的uniqid()重命名它们并将它们输入数据库;我想要为每个&#34; / img_tmp / 生成一组分组的字段。&#34;这允许我在将它们保存在DB中之前为每个属性设置属性。我之前发现的关于如何一次提交多个对象的所有资源都不完整或者过于复杂。

1 个答案:

答案 0 :(得分:1)

事实证明,我正在研究涉及弃用代码的解决方案,即我的自定义类型的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 %}

应用程序/配置/ 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']);
    }
}