kikwik / json-form-bundle
使用 dunglas/doctrine-json-odm 的表单辅助器和监听器
v1.0.2
2024-05-24 07:32 UTC
Requires
- php: >=8.1
- doctrine/doctrine-bundle: ^2.10
- dunglas/doctrine-json-odm: ^1.3
- symfony/form: ^6.3
- symfony/framework-bundle: ^6.3
This package is auto-updated.
Last update: 2024-09-24 08:09:30 UTC
README
使用 dunglas/doctrine-json-odm 的表单辅助器和监听器
安装
打开命令行控制台,进入你的项目目录,并执行以下命令以下载此包的最新稳定版本
$ composer require kikwik/json-form-bundle
使用
假设定义了一些模型
// first model namespace App\Model; class Dimension { private ?int $height = null; private ?int $width = null; // getter and setter... }
// second model namespace App\Model; class TechData { private ?string $someData = null; private ?string $otherData = null; // getter and setter... }
然后你必须为每个模型定义一个表单
// first model form namespace App\Form\Model; use App\Model\Dimension; class DimensionType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('height') ->add('width') ; } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class'=>Dimension::class ]); } }
// second model form namespace App\Form\Model; use App\Model\TechData; class TechDataType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('someData') ->add('otherData') ; } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class'=>TechData::class ]); } }
现在你可以定义一个具有一些 json_document
字段的实体,这些字段定义为单个模型或任意模型数组(实体必须有一个 updatedAt
时间戳字段)
// the entity namespace App\Entity; use App\Model\Dimension; #[ORM\Entity(repositoryClass: ProductRepository::class)] class Product { #[ORM\Column(type: Types::STRING)] private ?string $name = null; #[ORM\Column(type: 'json_document', nullable: true)] private ?Dimension $dimension = null; #[ORM\Column(type: 'json_document', nullable: true)] private array $techData = []; #[ORM\Column(type: Types::DATETIME_MUTABLE)] protected $updatedAt; // getter and setter... }
为了正确处理具有 json_document
字段的表单,你必须自动注入 JsonDocumentFormSubscriber
服务并将其添加到 FormBuilderInterface 作为事件监听器。
监听器将在其中一个 json_document 字段更改的情况下将 updatedAt
字段设置为当前时间戳。这将迫使 doctrine 持久化主实体。
// the entity form namespace App\Form; use Kikwik\JsonFormBundle\EventListener\JsonDocumentFormSubscriber; class ProductFormType extends AbstractType { public function __construct(private JsonDocumentFormSubscriber $jsonDocumentFormSubscriber) # autowire here { } public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('name') ->add('dimension',DimensionType::class) ->addEventSubscriber($this->jsonDocumentFormSubscriber) # add as event subscriber ; } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => Product::class, ]); } }
JsonDocumentCollectionType
为了处理模型集合,你必须定义模型到相关表单的映射,在 config/packages/kikwik_json_form.yaml
中。
kikwik_json_form: model_map: App\Model\Dimension: App\Form\Model\DimensionType App\Model\TechData: App\Form\Model\TechDataType
然后你可以使用 JsonDocumentCollectionType
将不同类型的模型存储在一个字段中
namespace App\Form; use Kikwik\JsonFormBundle\EventListener\JsonDocumentFormSubscriber; class ProductFormType extends AbstractType { public function __construct(private JsonDocumentFormSubscriber $jsonDocumentFormSubscriber) { } public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('name') ->add('techData',JsonDocumentCollectionType::class, [ 'model_labels' => [ 'App\Model\Dimension' => 'Size of product', 'App\Model\TechData' => 'Technical data', ] ]) ->addEventSubscriber($this->jsonDocumentFormSubscriber) ; } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => Product::class, ]); } }
要强制使用初始数据,请在 PRE_SET_DATA
监听器内部使用 data_models
选项
namespace App\Form; use Kikwik\JsonFormBundle\EventListener\JsonDocumentFormSubscriber; class ProductFormType extends AbstractType { public function __construct(private JsonDocumentFormSubscriber $jsonDocumentFormSubscriber) { } public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('name') ->add('techData',JsonDocumentCollectionType::class, [ 'model_labels' => [ 'App\Model\Dimension' => 'Size of product', 'App\Model\TechData' => 'Technical data', ] ]) ->addEventSubscriber($this->jsonDocumentFormSubscriber) ; $builder->addEventListener(FormEvents::PRE_SET_DATA, [$this, 'onPreSetData']); } public function onPreSetData(PreSetDataEvent $event) { /** @var Product $product */ $product = $event->getData(); $form = $event->getForm(); if(!$product || $product->getId() == null) { $form->add('techData',JsonDocumentCollectionType::class, [ 'model_labels' => [ 'App\Model\Dimension' => 'Size of product', 'App\Model\TechData' => 'Technical data', ], 'data_models' => [ 'App\Model\Dimension', 'App\Model\TechData' ] ]); } } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => Product::class, ]); } }