嵌入自定义时猜测自定义表单类型 类
Guess custom form type when embedding custom classes
我的应用模型有两个简单的 类:Money
和 Product
。
由于 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。
我的应用模型有两个简单的 类:Money
和 Product
。
由于 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。