kikwik / json-form-bundle

使用 dunglas/doctrine-json-odm 的表单辅助器和监听器

安装: 13

依赖: 0

建议者: 0

安全: 0

星星: 0

关注者: 1

分支: 0

开放问题: 0

类型:symfony-bundle

v1.0.2 2024-05-24 07:32 UTC

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,
        ]);
    }
}