无法使用键阵列子集访问数组中的表单值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法使用键阵列子集访问数组中的表单值相关的知识,希望对你有一定的参考价值。

对于一个项目,我正在与一家公司合作,该公司的地址与该公司相关。我用它的物理地址为公司创建了一个表单(这个地址总是存在,它还有与之关联的额外地址。这是我遇到问题的地方。

我正在使用CollectionType为表单为每个额外的地址使用相同的表单。我正在创建一个表格,其中包含额外地址的预填充值(可以是1,2,3或甚至4个地址),使用:

    $form_adressen = $this
        ->createForm(AdressenType::class, $result['extra_address'])
        ->handleRequest($request)
    ;

但是,这不会呈现表单,也不会从控制器中获取任何值。但是,以下代码有效:

    $form_adressen = $this
        ->createForm(AdressenType::class, $result)
        ->handleRequest($request)
    ;

结果['extra_address']打印以下数据:

Array
(
    [1059] => Array
        (
            [AdrGid] => 1059
            [AdrCode] => the address type
            [AdrStraat] => streetname
            [AdrHuisnummer] => number
            [AdrPostcode] => postal code
            [AdrPlaats] => cityname
            [AdrTelefoon] => telephone
            [AdrTelefoon2] => mobile
            [AdrTelefax] => fax
            [AdrNawGid] => 332 //id of companyaddress associating to this 'extra' address
            [NawFactuurAdres] => 1
            [AdrOms] => address type description
        )
        [...] // More addresses
}

$result给了我这个:

Array
(
    [company] => Array
        (
            [AdrGid] => 332
            [NawFilZoekcode] => company code
            [AdrNaam1] => company name
            [email2] => company mail
            [NawWebsite] => company website
            [email1] => second company email
            [AdrStraat] => streetname
            [AdrHuisnummer] => number
            [AdrPostcode] => postal code
            [AdrPlaats] => cityname
            [LndOms] => country
            [AdrTelefoon] => telephone
            [AdrTelefoon2] => mobile
            [AdrTelefax] => fax
            [NawFactuurAdres] => 1
            [AdrCode] => adrress type
            [AdrOms] => address type description
        )

    [extra_address] => Array
        (
            [1059] => Array
                (
                    [AdrGid] => 1059
                    [AdrCode] => address type
                    [AdrStraat] => streetname
                    [AdrHuisnummer] => number
                    [...] // etc etc

我的结果数组如下所示:

foreach ($company as $row) {
    $dataFields = [
        [...]
    ];
    foreach ($dataFields as $dataField) {
        if (empty($result['gegevens'][$dataField])) {
            $result['company'][$dataField] = $row[$dataField];
        }
    }
    if ($row['AdrGid'] != $result['gegevens']['AdrGid']) {
        $result['extra_address'][$row['AdrGid']] = [
            [...]
        ];
    }
}

编辑:我的AdressenType创建表单:

class AdressenType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('addresses', CollectionType::class, [
                'entry_type' => AddressType::class
            ])
        ;
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
        ));
    }
    public function getBlockPrefix()
    {
        return 'appbundle_form_adressenform';
    }
}
class AddressType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            [...] // Add fields
        ;
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
        ));
    }
}

这是我将表单传递给视图的方式:

return $this->render('pages/company/edit.html.twig', array(
    'client' => $result,
    'form' => $form->createView(),
    'form_adressen' => $form_adressen->createView()
));

正如您所看到的,extra_address循环使用id作为数组的键,我猜这就是地址未在视图中显示或呈现的原因。

我使用以下代码遍历每个表单:

{{ form_start(form_adressen, {'  method': 'POST'}) }}
{{ form_row(form_adressen._token) }}
{% for adres in form_adressen.addresses %} // here 'addresses' is my form collectionType, not to be confusing
    [...] // form_widgets, etc
{{ endfor }}
{{ form_end(form_adressen) }}

其中form_adressen是我的formType名称,'addresses'是form_adressen formType的collectionType。

我的问题是,如果每个地址的数组ID为关键字,我如何用数据填写地址表单?我的猜测是表单无法识别键,因此它会跳过。

答案

当前的AdressenType试图在['addresses']找到它的数据,但是在控制器中你通过直接传递额外地址列表来创建表单。

->createForm(AdressenType::class, $result['extra_address'])

这个数组可能没有密钥'addresses',因此表单就像没有条目一样。

所以要么:

  1. 传递正确的数据: ->createForm(AdressenType::class, [ 'addresses' => $result['extra_address'] ])
  2. AdressenType中的密钥更改为'extra_address'并传入$result$builder ->add('extra_address', CollectionType::class, [ 'entry_type' => AddressType::class ]) ; ->createForm(AdressenType::class, $result)
  3. 或者更好,改变AdressenType直接扩展CollectionType。哪个(恕我直言)是更好/更清洁的事情,因为它删除了对任意数组键的依赖: <?php // ... use SymfonyComponentFormExtensionCoreTypeCollectionType; class AdressenType extends AbstractType { /** * @inheritdoc */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'entry_type' => AddressType::class, ]); } /** * @inheritdoc */ public function getParent() { // extend the collection type return CollectionType::class; } } 有: ->createForm(AdressenType::class, $result['extra_address']) 在视图中,您可以将其用作: <h4>Extra addresses</h4> {{ form_start(form_adressen) }} {% for address in form_adressen.children %} {{ form_errors(address) }} {{ form_widget(address) }} <br> {% endfor %} <button>Submit</button> {{ form_end(form_adressen) }}

使用第三个选项,当您尝试自定义表单呈现时,可能会遇到问题。像这样使用自动注入的csrf-token将是地址的兄弟。如果您尝试访问每个子项的单个字段,这可能会导致错误。

虽然以下情况应该适用于这种情况:

{% for key, value in form_adressen.vars.data %}
    {{ form_row(form_adressen.children[key].AdrStraat) }}
    {{ form_row(form_adressen.children[key].AdrHuisnummer) }}
    {{ form_row(form_adressen.children[key].AdrPostcode) }}
    <br>
{% endfor %}

以上是关于无法使用键阵列子集访问数组中的表单值的主要内容,如果未能解决你的问题,请参考以下文章

带有 mat-select 的角度动态表单无法获取值访问器

从表单中的选择列表中发送值而不是键

如何使用核心数据访问保存在不同视图控制器中的阵列?

使用无效键值访问的 JArray 值:“字段”。预期数组位置索引

光线投射和二维阵列在 Unity 中的魔方无法按预期工作

AJAX 全局阵列存储