首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >symfony 2.3表单getData在subforms集合中不起作用

symfony 2.3表单getData在subforms集合中不起作用
EN

Stack Overflow用户
提问于 2013-09-18 19:20:12
回答 5查看 10.7K关注 0票数 9

我有一个包含集合的表单。所以我有:

代码语言:javascript
复制
/* my type */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
    ->add('name')
    ->add('photos','collection',array(
        'type'=> new PhotoType(),
        'allow_add'=>true));
}

/*Photo Type*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
    ->add('photoname')
    ->add('size')
}

但是我想访问照片中的数据,所以我在PhotoType中尝试:

代码语言:javascript
复制
$data = $builder->getData();

但它似乎不工作,即使我正在编辑表单,所以照片收集有数据。为什么我不能在另一个调用的表单中访问$builder->getData()?因为我试着不去做而eventListener..。

EN

回答 5

Stack Overflow用户

发布于 2013-09-19 01:42:44

要了解这里发生了什么,您必须首先了解数据映射。当你调用

代码语言:javascript
复制
$form->setData(array('photoname' => 'Foobar', 'size' => 500));

表单的数据映射器负责获取给定的数组(或对象)并将嵌套的值写入表单的字段,即调用

代码语言:javascript
复制
$form->get('photoname')->setData('Foobar');
$form->get('size')->setData(500);

但是在您的示例中,您处理的不是Form,而是FormBuilder对象。FormBuilder负责收集表单的配置并使用此信息生成Form实例。因此,FormBuilder还允许您存储表单的默认数据。但是因为它只是一个简单的配置对象,所以到目前为止它还不会调用数据映射器。例如:

代码语言:javascript
复制
$builder = $factory->createBuilder()
    ->add('photoname')
    ->add('size')
    ->setData(array('photoname' => 'Foobar', 'size' => 500));

print_r($builder->get('photoname')->getData());
print_r($builder->get('size')->getData());

此示例将输出:

代码语言:javascript
复制
null
null

因为当我们将FormBuilder转换为Form实例时,数据映射会在稍后发生。我们可以使用这一事实为各个字段设置单独的默认值:

代码语言:javascript
复制
$builder->add('size', null, array('data' => 100));
// which is equivalent to
$builder->get('size')
    ->setData(100)
    ->setDataLocked(true);

print_r($builder->get('photoname')->getData());
print_r($builder->get('size')->getData());

和输出:

代码语言:javascript
复制
null
100    

数据锁定是为了防止数据映射器覆盖您刚刚存储的默认数据。如果您传递"data“选项,则会自动完成此操作。

最后,您将构建表单。现在,FormBuilder在必要时调用Form::setData(),后者将调用数据映射器:

代码语言:javascript
复制
$form = $builder->getForm();

// internally, the following methods are called:

// 1) because of the default data configured for the "size" field
$form->get('size')->setData(100);

// 2) because of the default data configured for the main form
$form->setData(array('photoname' => 'Foobar', 'size' => 500));

// 2a) as a result of data mapping
$form->get('photoname')->setData('Foobar');

// 2b) as a result of data mapping (but ignored, because the data was locked)
$form->get('size')->setData(500);
票数 23
EN

Stack Overflow用户

发布于 2014-05-10 07:22:45

正如Bernhard指出的那样,侦听器是实现此目的的唯一方法,因为数据在子窗体中还不可用。我使用eventListener解决了类似的需求。下面是我的代码的一个简化版本,我希望它能对你有所帮助:

我的View实体有一个父表单,它有很多字段,以及其他表单的集合。其中一个子表单用于关联的实体ViewVersion,它实际上需要为动态实体加载另一个表单集合,该动态实体是与View关联的内容类型。此内容类型可以是许多不同类型的实体之一,例如文章、个人资料等。因此,我需要找出在View数据中设置了什么contentType,然后找到指向该捆绑包的动态路径,并包含该formType。

一旦你知道如何做,它实际上是很容易的!

代码语言:javascript
复制
class ViewType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // Basic Fields Here
            // ...
            // ->add('foo', 'text')
            // ...
            // Load a sub form type for an associated entity
            ->add('version', new ViewVersionType())
        ;
    }
}



class ViewVersionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // Basic Fields Here
            // ...
            // ->add('foo', 'text')
            // ...
        ;

        // In order to load the correct associated entity's formType, 
        // I need to get the form data. But it doesn't exist yet.
        // So I need to use an Event Listener
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            // Get the current form
            $form = $event->getForm();
            // Get the data for this form (in this case it's the sub form's entity)
            // not the main form's entity
            $viewVersion = $event->getData();
            // Since the variables I need are in the parent entity, I have to fetch that
            $view = $viewVersion->getView();
            // Add the associated sub formType for the Content Type specified by this view
            // create a dynamic path to the formType
            $contentPath = $view->namespace_bundle.'\\Form\\Type\\'.$view->getContentType()->getBundle().'Type';
            // Add this as a sub form type
            $form->add('content', new $contentPath, array(
                'label' => false
            ));
        });

    }
}

就这样。我刚接触Symfony,所以在EventListener中做所有事情的想法对我来说都是陌生的(而且似乎不必要地复杂)。但我希望,一旦我更好地理解了这个框架,它看起来会更直观。如本例所示,使用事件侦听器并不复杂,只需将代码封装在该闭包中(或将其作为described in the docs放入它自己的单独函数中)。

我希望这对某些人有帮助!

票数 3
EN

Stack Overflow用户

发布于 2014-09-09 23:30:40

在提交或正在编辑时,可以在将FormBuilder转换为表单实例时访问数据。对于集合类型,您可以尝试这样做:

代码语言:javascript
复制
...
$form = $formBuilder->getForm();
...
if ($this->getRestMethod() == 'POST') {
    $form->handleRequest($this->get('request'));
    if ($form->isValid()) {
        $formData = $form->getData();
        foreach ($formData['photos'] as $key => $collectionRow) {
            var_dump($collectionRow['photoname']);
            var_dump($collectionRow['size']);
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18870866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档