Symfony CollectionType of Entities

时间:2018-03-07 07:24:56

标签: php symfony symfony-3.4

我正在开发一个没有Doctrine的Symfony 3.4上的项目(我们使用类似于Eloquent的自制ORM)并且一直试图制作我使用的实体的CollectionType:IntroductionSlide。

表格如下:

What the form looks like when rendered

您可以添加或删除IntroductionSlides,每个IntroductionSlide仅由其图像定义。由于图像取决于区域设置,因此它由TranslatableImageType处理,该类型为每个区域设置创建一个字段。单击小标志可以选择目标语言环境的输入字段。

以下是我的代码:

创建CollectionType:

case 'introduction_slides':
    $options['label'] = "Pages de présentation";
    $options['entry_type'] = IntroductionSlideType::class;
    $options['allow_add'] = true;
    $options['allow_delete'] = true;
    $options['attr']['class'] = "introduction-slides";
    $options['required'] = false;
    $this->form->add($field, CollectionType::class, $options);
    break;

IntroductionSlideType:

<?php

namespace AppBundle\Form\Type;

use AppBundle\Model\IntroductionSlide;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;

class IntroductionSlideType extends AbstractType
{
    public function buildView(FormView $view, FormInterface $form, array $options)
    {}

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $options['mapped'] = false;
        $builder->add("images", TranslatableImageType::class, $options);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => IntroductionSlide::class,
        ));
    }
}

和TranslatableImageType:

<?php

namespace AppBundle\Form\Type;

use AppBundle\EventSubscriber\StaticConfig;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\Image;

class TranslatableImageType extends AbstractType
{
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['locales'] = $options['locales'];
        $view->vars['locale'] = $options['locale'];
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $file_options = array_merge($options, $options["field_options"]);

        unset($file_options['locales'], $file_options['locale'], $file_options["field_options"]); // not valid text options
        $file_options['compound'] = false; // sub items are simple widgets

        $file_options['constraints'] = [new Image([
            'mimeTypes' => ["image/png", "image/jpg", "image/jpeg", "image/gif"],
            'mimeTypesMessage' => "Seul un fichier avec l'extension png, jpg, jpeg ou gif peut être uploadé.",
            "maxSize" => "7M",
            'maxSizeMessage' => "Ce fichier est trop volumineux ({{ size }} {{ suffix }}). La limite de volume est de {{ limit }} {{ suffix }}.",
        ])];

        foreach ($options['locales'] as $locale) {
            $file_options['attr']['lang'] = $locale;
            $builder->add($locale, FileType::class, $file_options);
        }
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => null,
        ));

        $resolver->setDefaults(array(
            'locales' => StaticConfig::getLocales(),
            'locale' => StaticConfig::getLocale(),
            'field_options' => [],
        ));
    }

    public function getBlockPrefix()
    {
        return 'translatableImage';
    }
}

这就是我在想Symfony会做什么(没有数据传递给集合):
 1.定义CollectionType
 2.在CollectionType中定义IntroductionSlideType  3.实例化一个空的IntroductionSlide并使用作为IntroductionSlideType的数据  4.为构建器创建一个字段“images”并调用$ IntroductionSlide-&gt; getImages()来提供其值  5.在IntroductionSlideType中定义TranslatableImageType  6.使用$ IntroductionSlide-&gt; getImages()的返回值作为数据(包含locale =&gt; image_name的数组)

相反,Symfony会触发异常:

Cannot read index "0" from object of type "AppBundle\Model\IntroductionSlide" because it doesn't implement \ArrayAccess.

我不明白为什么它会尝试在IntroductionSlide中达到索引“0”。

设置断点显示,当Symfony尝试在IntroductionSlideType中构建字段“images”时会发生这种情况。

添加$ options ['mapped'] = false;到$ builder-&gt; add(“images”,TranslatableImageType :: class,$ options);使其能够在不触发异常的情况下到达视图 提交表单时,在表单组件处理数据之后,这是它的样子:

Empty arrays of arrays

0 个答案:

没有答案