【问题标题】:Symfony 5 - Form - Choice valueSymfony 5 - 形式 - 选择值
【发布时间】:2021-08-03 14:03:17
【问题描述】:

我想制作一个带有显示不同选项的选择字段的表单。 这些选项是NomenclatureDTO 对象字段$libNom 的列表设置为:

class NomenclatureDTO
{
    public int $idNom;
    public string $libNom;
    public string $dtMiseEnPlace;
    public string $dtObsolescence;
}

这是表单适用的类:

class AvisDTO
{
    public string $dtAvis;
    public string $dtEmission;
    public string $idActeurAuteur;
    public string $nomAuteur;
    public string $prenomAuteur;
    public bool $boEstTacite;
    public ArrayCollection $documents;
    public string $idConsultation;
    public array $idsPieces;
    public int $nomNatureAvisRendu;
    public int $nomTypeAvis;
    public string $txAvis;
    public string $txFondementAvis;
    public string $txHypotheses;
    public string $txQualiteAuteur;

    public function __construct()
    {
        $this->documents = new ArrayCollection();
    }    
}

我想在选择选项中显示libNom,但我只需要在提交时使用idNom

所以,我的表单看起来像:

<?php

namespace App\Form;

use App\Entity\DTO\AvisDTO;
use App\Entity\DTO\DataFormMapper\DataAvisType;
use App\Entity\DTO\NomenclatureDTO;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ChoiceList;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AvisType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // dd($options['dataPostAvis']->nomNatureAvisRendu);      L21: SCREENSHOT
        $builder
            ->add('nomAuteur', TextType::class, [
                'label' => "Nom",
            ])
            ->add('prenomAuteur', TextType::class, [
                'label' => "Prénom"
            ])
            ->add('boEstTacite', ChoiceType::class, [
                'required' => true,
                'label' => "L'avis est-il tacite ?",
                'label_attr' => [
                    'class' => "font-weight-bold"
                ],
                'expanded' => true,
                'multiple' => false,
                'choices' => [     
                    'Oui' => true,
                    'Non' => false,                     
                ],                      
            ])          
            ->add('nomNatureAvisRendu', ChoiceType::class, [
                'label' => "Nature de l'avis rendu",
                'required' => false,                
                'choices' => $options['dataPostAvis']->nomNatureAvisRendu,
                'choice_label' => function(?NomenclatureDTO $choice) {                    
                    return $choice->libNom;
                },
                'choice_value' => function(?NomenclatureDTO $choice) {  
                    // dd($choice);                              L50: SCREENSHOT
                    // dd(gettype($choice->idNom), $choice->idNom);L51: SCREENSHOT
                    return $choice->idNom;
                },
            ])
            ->add('nomTypeAvis', ChoiceType::class, [
                'label' => "Type d'avis",
                'required' => false,
                'choices' => $options['dataPostAvis']->nomTypeAvis,
                'choice_label' => function($choice) {                   
                    return $choice->libNom;
                },                              
                'choice_value' => ChoiceList::value($this, 'idNom'),
            ])
            ->add('txAvis', TextareaType::class, [
                'required' => true,
                'attr' => [
                    'placeholder' => "Avis favorable avec prescriptions. \nPremière prescription : Les volets doivent être en bois"
                ]
            ])
            ->add('txFondementAvis', TextareaType::class, [
                'attr' => [
                    'placeholder' => "L'avis de l'ABF est rendu en application de l'article R. 425-30 du Code de l'urbanisme."
                ]
            ])
            ->add('txHypotheses', TextareaType::class, [
                'attr' => [
                    'placeholder' => "Dans l'hypothèse où la puissance électrique nécessaire est de x alors le coût de raccordement est de y"
                ]
            ])
            ->add('txQualiteAuteur', TextareaType::class, [
                'attr' => [
                    'placeholder' => "Qualité"
                ]
            ])

            ->add('Envoyer', SubmitType::class, [
                'row_attr' => [
                    'class' => 'row justify-content-end'
                ],
            ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => AvisDTO::class,
            'dataPostAvis' => DataAvisType::class,          
        ]);
    }
}

屏幕截图 L21:

屏幕截图 L50:

屏幕截图 L51:

我在页面实际显示表单之前收到此错误:

注意:试图获取非对象的属性 'idNom'

这对我来说毫无意义,因为转储 L51 明确表示 $choiceNomenclatureDTO 对象...

编辑

我尝试设置:

->add('nomNatureAvisRendu', ChoiceType::class, [
    'label' => "Nature de l'avis rendu",
    'required' => false,                
    'choices' => $options['dataPostAvis']->nomNatureAvisRendu,
    'choice_label' => function(?NomenclatureDTO $choice) {                    
        return $choice ? $choice->idNom : null;
    },
    'choice_value' => static function(?NomenclatureDTO $choice): int {  
        return $choice->idNom ?? 0;     
    },
])

提交时返回:

类型属性 App\Entity\DTO\AvisDTO::$nomNatureAvisRendu 必须是 int, App\Entity\DTO\NomenclatureDTO 使用

【问题讨论】:

    标签: php symfony symfony-forms choicefield


    【解决方案1】:

    选择可能是正确的,但是当使用dd($choice) 时,您只验证了一个选择。因为该字段不是必需的,所以也许还有一个空值传递给您的回调函数?在任何情况下,您的匿名方法都使用?NomenclatureDTO,它允许空值。我想你可以使用return $choice?-&gt;idNom; (php8) 或类似return $choice ? $choice-&gt;idNom : null;

    另一件可能值得检查的是映射对象中属性的数据,它也可能为空。我认为一旦选项可以处理空值,这应该不会导致问题。

    【讨论】:

    • 我试过“return $choice ? $choice->idNom : null;”但我仍然得到同样的错误:(类型属性 App\Entity\DTO\AvisDTO::$nomTypeAvis 必须是 int,App\Entity\DTO\NomenclatureDTO 使用)而且我的数据都满足字段 $idNom 和 $libNom.. .
    • 对我来说这看起来像是一个完全不同的错误。该错误与nomTypeAvis 有关,与nomNatureAvisRenduidNom 属性无关。因此,似乎至少解决了一个问题;)我想如果您使用类似的方法(使用回调而不是ChoiceList::value),您可以解决新错误。或者,您可能只使用那里的属性名称(请参阅symfony.com/doc/current/reference/forms/types/… 中的“这可以是可调用的或属性路径”)
    • 如果我用 return "return $choice ? $choice->idNom : null;" 设置这两个属性,我仍然有错误:"Typed property App\Entity\DTO\AvisDTO::$ nomNatureAvisRendu 必须为 int,使用 App\Entity\DTO\NomenclatureDTO”。
    【解决方案2】:

    所以最终的答案是在 AvisDTO 类中设置它:

        public NomenclatureDTO $nomNatureAvisRendu;
        public NomenclatureDTO $nomTypeAvis;
    

    您需要映射整个对象,而不仅仅是一个字段...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-30
      • 1970-01-01
      • 2011-08-21
      • 2021-05-08
      • 2019-10-25
      • 2013-04-26
      相关资源
      最近更新 更多