嵌入自定义时猜测自定义表单类型 类

Guess custom form type when embedding custom classes

我的应用模型有两个简单的 类:MoneyProduct

由于 Money 应用程序表单可重复使用,我决定创建 MoneyType 扩展 AbstractType

// App\Entity\Product

/**
* @ORM\Embedded(class="Money\Money")
*/
private $price;
// App\Form\ProductType

$builder->add('price', MoneyType::class)
// App\Form\Type\MoneyType

class MoneyType extends AbstractType
{
    private $transformer;

    public function __construct(MoneyToArrayTransformer $transformer)
    {
        $this->transformer = $transformer;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('amount', NumberType::class, [
                'html5' => true,
                'constraints' => [
                    new NotBlank(),
                    new PositiveOrZero(),
                ],
                'attr' => [
                    'min' => '0',
                    'step' => '0.01',
                ],
            ])
            ->add('currency', ChoiceType::class, [
                'choices' => $this->getCurrenciesChoices(),
                'constraints' => [
                    new NotBlank(),
                ],
            ]);

        $builder->addModelTransformer($this->transformer);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        parent::configureOptions($resolver);

        $resolver->setDefaults([
            'data_class' => null
        ]);
    }

    ...
}

是否可以在不明确指定的情况下猜测字段类型以获得以下代码?

// App\Form\ProductType

$builder->add('price')

欢迎任何帮助。提前谢谢你。

Form TypeGuesser 主要基于注释 @var Money\Money,您应该能够为自己的类型构建向下猜测器,请参阅 https://symfony.com/doc/current/form/type_guesser.html

另请参阅 https://github.com/symfony/symfony/blob/4.3/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php 如何根据学说或特定类型猜测类型。

您可以通过这两个示例推导出您自己的特定于应用程序的猜测器。

您可以实施 custom TypeGuesser that reads the doctrine metadata 并检查该字段是否是所需类型的可嵌入字段。这是一个基本的实现

namespace App\Form\TypeGuesser;

use App\Form\Type\MoneyType;

use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\FormTypeGuesserInterface;

use Doctrine\ORM\EntityManagerInterface;

class MoneyTypeGuesser implements FormTypeGuesserInterface
{
    private $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;    
    }

    public function guessType($class, $property) 
    {
        if (!$metadata = $this->em->getClassMetadata($class)) {
            return null;
        }

        if (
            isset($metadata->embeddedClasses[$property]) && 
            'Money\Money' == $metadata->embeddedClasses[$property]['class']
        ) {
            return new TypeGuess(MoneyType::class, [], Guess::HIGH_CONFIDENCE);
        }
    }

    // Other interface functions ommited for brevity, you can return null
}

您可以看到所有需要实现的接口方法here