我正在开发一个没有Doctrine的Symfony 3.4上的项目(我们使用类似于Eloquent的自制ORM)并且一直试图制作我使用的实体的CollectionType:IntroductionSlide。
表格如下:
您可以添加或删除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);使其能够在不触发异常的情况下到达视图 提交表单时,在表单组件处理数据之后,这是它的样子: