Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Forms symfony 2.3表单getData不';无法在子窗体集合中工作_Forms_Symfony_Collections_Builder - Fatal编程技术网

Forms symfony 2.3表单getData不';无法在子窗体集合中工作

Forms symfony 2.3表单getData不';无法在子窗体集合中工作,forms,symfony,collections,builder,Forms,Symfony,Collections,Builder,我有一个包含集合的表单。因此,我: /* my type */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name') ->add('photos','collection',array( 'type'=> new PhotoType(), 'allow_add'=>true))

我有一个包含集合的表单。因此,我:

/* 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')
}
但是我想访问照片中的数据,所以我尝试在照片类型中:

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

要理解这里发生了什么,你必须先理解数据映射。当你打电话的时候

$form->setData(array('photoname' => 'Foobar', 'size' => 500));
表单的数据映射器负责获取给定的数组(或对象)并将嵌套值写入表单的字段,即调用

$form->get('photoname')->setData('Foobar');
$form->get('size')->setData(500);
但在您的示例中,您处理的不是
Form
,而是
FormBuilder
对象
FormBuilder
负责收集表单的配置,并使用此信息生成
form
实例。因此,
FormBuilder
还允许您存储表单的默认数据。但是,由于它只是一个简单的配置对象,因此目前还不会调用数据映射器。例如:

$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());
此示例将输出:

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

$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());
以及输出:

null
100    
需要数据锁定以防止数据映射器覆盖您刚才存储的默认数据。如果您传递“数据”选项,这将自动完成

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

$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);

正如Bernhard指出的,侦听器是实现这一点的唯一方法,因为数据在子表单中还不可用。我使用eventListener来解决类似的需求。下面是我的代码的简化版本,希望对您有所帮助:

我的
视图
实体有一个父表单,它有许多字段,以及其他表单的集合。其中一个子表单用于关联实体
ViewVersion
,它实际上需要为动态实体加载另一个表单集合,该动态实体是与
视图关联的内容类型。此内容类型可以由许多不同类型的实体之一来定义,例如文章、配置文件等。因此,我需要找出
视图
数据中设置的内容类型,然后找到该捆绑包的动态路径,并包括该表单类型

一旦你知道怎么做,其实很容易

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中做任何事情的想法对我来说都是陌生的(而且似乎不必要的复杂)。但我希望,一旦我更好地理解了这个框架,它将看起来更加直观。如本例所示,使用事件侦听器并不复杂,只需将代码包装在该闭包中(或将其作为一个单独的函数放在它自己的函数中)


我希望这能帮助别人

在提交或编辑过程中,可以在将FormBuilder转换为表单实例时访问数据。对于集合类型,您可以尝试以下方法:

...
$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']);
        }
    }
}

在我的例子中,在构建表单时不一定需要数据,但在构建视图时(稍后)。在我的子表单类型类的buildForm函数旁边,我添加了buildView函数:

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;

class MyType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ...
    }

    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $data = $form->getData();
        $view->vars['name'] = $data->objproporwhatever;
    }

    // ...
}
由于buildView稍后调用,因此数据在那里可用。在本例中,我使用它更改集合中每个项的表单行的标签。签出。

要添加到Chadwick Meyer(在Symfony 4中,但可能适用于早期版本),需要一个事件侦听器来访问集合中的数据,因为很多时候数据尚未创建和/或尚未关联或嵌入到集合中。然而,在日常使用中,通过事件侦听器获取集合中的数据变得非常重要,这与实际获取数据有一些复杂的关系

在照片表单生成器中,必须包含一个事件侦听器:

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

        $builder->addEventListener(FormEvents::POST_SET_DATA,
             function (FormEvent $event)  {

                $form = $event->getForm();

                // this would be your entity
                 $photo = $event->getData();

                //Do something with the photo data.
            }
        );

    }
然而。。。如果您想对它做些什么,您需要确保测试空值,因为在实际动态创建数据之前和之后会多次触发事件。例如,如果要动态修改表单,如添加某种提交按钮:

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


    $builder->addEventListener(FormEvents::POST_SET_DATA,
         function (FormEvent $event) use ($formModifier) {

                $form = $event->getForm();
                // this would be your entity
                 $photo = $event->getData();

                $formModifier($form,$photo);
         }
    );

    $formModifier = function (FormInterface $form, Photo $photo = null) {

        if (!empty($photo)){//Critical to do this test to avoid errors and get to events with data 
            $form->add('submitButton', SubmitType::class, array(
                 'label' => 'Do Something',
                ));
            }

    };
}

最后,请注意,在某些情况下,并非所有数据都与特定实体关联,直到它实际持久化到数据库中。例如,如果实体是新创建的,那么它还没有id,而id通常是在持久化过程中由条令或类似规则自动生成的。因此,为了在持久化之前将提交按钮或类似项与集合中的此实体关联,您可能必须使“name”字段唯一,或者为实体创建一个单独的字段,以保存唯一的类型参数,并在持久化之前以唯一的方式生成它,以便在表单创建期间将提交按钮之类的内容与实体相关联。

您尝试使用
getData()访问数据的位置和原因
?您只描述了什么不起作用,而不是您试图做什么:),但我猜您想使用事件侦听器:我正在尝试做事件侦听器不使用事件侦听器时所做的事情。我只想使用$builder->getData()来查看对象的一些变量,就像在一级表单(不是子表单)中一样。有办法吗?没有,对不起。这就是事件侦听器的用途(我希望我能解释原因)。如果有人能解释为什么您可以在父formBuilder中访问$builder->getData(),但在关联实体的子formType中,您不能,那就太好了。我认为,如果不是整个表单数据,那么子类型关联实体的变量对象至少应该是可访问的。如何访问此子fo中的数据