如何将数据传递到 CollectionType 表单并将其获取到那里?

How to pass data into CollectionType form and get it there?

如何以正确的方式获取发送到集合中的数据?

重要:

If I delete from the Create Form class this line:

'data'=> array_values($builder->getData()->cpus), //TODO: shit code send data And add in Collection 

And add in Collection Form class this:

'data_class' => Command::class, //namespace (Collection\Command)

This works only in view (twig) stage, but firstly I have to get those data before creating collection form (view).

我该怎么做?

此刻我找到了这个解决方案(看起来 "shitty"):)。标记为 TODO

的行

Collection\Command:

class Command
{
    public $id_item;
    /**
     * @var ItemInterface $interface
     */
    public $interface;
    public $id_object;

    public function __construct(string $id_item, ItemInterface $interface)
    {
        $this->id_item = $id_item;
        $this->interface = $interface;
    }

    public function getIdItem(): string
    {
        return $this->id_item;
    }

    public function getInterface(): ItemInterface
    {
        return $this->interface;
    }
}

有问题,我无法很好地从 $cpus 获取数据 :)

Collection\Form:

class Form extends AbstractType
{
    private $cpuModelFetcher;

    public function __construct(CpuModelFetcher $cpuModelFetcher)
    {
        $this->cpuModelFetcher = $cpuModelFetcher;
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $index = (int)$builder->getName(); //TODO: shit code - use name of form as index.
        /**
         * @var Command $command
         */
        $command = $builder->getData()[$index]; //TODO: shit code get data from array

        $builder
            ->add('id_object', Type\ChoiceType::class,
                [
                    'choices' => array_flip($this->cpuModelFetcher->getSupportedCpuModelListForModelBasedDeviceBySocketType(
                        $command->getIdItem(),$command->getInterface()->getId())),
                    'placeholder' => 'not installed in '.$command->getInterface()->getName().' socket.',
                    'required' => false,
                ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults(array(
            //'data_class' => Command::class,
            'data_class' => null,
        ));
    }
}

创建命令:

class Command
{
    /**
     * @Assert\NotBlank()
     */
    private $id;
    public $cpus;

    private function __construct(Id $id)
    {
        $this->id = $id;
    }

    public static function fromDevice(Device $device): self
    {
        $command = new self($device->getId());
        if($device->getBasedType()->isModelBasedDevice()){
            $command->cpus = $command->transformDeviceModelInterfaceCollectionToCommandArray($device->getId(),
                $device->getModelBasedDevice()->getDeviceModel()->getCpuInterfaces());
        }

        return $command;
    }

    private function transformDeviceModelInterfaceCollectionToCommandArray(Id $id_item, ArrayCollection $interfaces): array
    {
        $object_specific_interfaces = [];
        foreach ($interfaces as $one){
            /**
             * @var DeviceModelInterface $one
             */
            for($i=0; $i<$one->getAmount(); $i++){
                $object_specific_interfaces[] = new Collection\Command($id_item->getValue(), $one->getInterface());
            }
        }
        unset($one);
        return $object_specific_interfaces;
    }
}

创建表单:

class Form extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        //dump($builder);
        $builder
            ->add('cpus', CollectionType::class, [
                'label' => false,
                'entry_type' => Collection\Form::class,
                'entry_options' => [
                    'label' => false,
                    'data'=> array_values($builder->getData()->cpus), //TODO: shit code send data
                ],
                'by_reference' => true,
                'allow_add' => false,
                'allow_delete' => false,
                'delete_empty' => true,
            ])
            ->add('save', Type\SubmitType::class, [
                'attr' => ['class' => 'btn btn-primary'],
            ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults(array(
            'data_class' => Command::class,
        ));
    }
}

感谢您的帮助。

我发现这个解决方案看起来更好,我只是从 class Collection\Form.

中的 PRE_SET_DATA 事件中获取数据
class Form extends AbstractType
{
    private $cpuModelFetcher;

    public function __construct(CpuModelFetcher $cpuModelFetcher)
    {
        $this->cpuModelFetcher = $cpuModelFetcher;
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {

        $builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));
    }

    protected function addElements(FormInterface $form, $data): void
    {
        /**
         * @var Command $data
         */
        $form->add('id_object', Type\ChoiceType::class,
            [
                'choices' => array_flip($this->cpuModelFetcher->getSupportedCpuModelListForModelBasedDeviceBySocketType(
                    $data->getIdItem(), $data->getInterface()->getId())),
                'placeholder' => 'not installed in '.$data->getInterface()->getName().' socket.',
                'required' => false,
            ]);
        //dump($data);
        //dump($form);
    }

    function onPreSetData(FormEvent $event): void
    {
        $form = $event->getForm();
        $data = $event->getData();

        $this->addElements($form, $data);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults(array(
            'data_class' => Command::class,
        ));
    }
}

无论如何,如果有人知道其他解决方案,我将很高兴听到。

谢谢。