2017-06-02 92 views
0

我有一个属性的实体被设置为阵列阵列类型属性和形式CollectionType与数据变换器

/** 
* @ORM\Column(type="array") 
*/ 
private $labels = []; 

此数组的标签的数据存储翻译等

[ 
    'en' => 'foo-in-English', 
    'de' => 'foo-in-German', 
    'ru' => 'foo-in-Russian' 
] 

我有像标签设置类型的一种形式:

$builder 
    ->add('labels', CollectionType::class); 

注意,entry_type默认(正确)到TextType这里。保留原样,模板将与文本字段中显示,如:

Labels:  en: _____FOO IN ENGLISH____ 
       de: _____FOO IN GERMAN_____ 
       ru: _____FOO IN RUSSIAN____ 

不过,我想用实际的语言,而不是两个字母代码作为显示的字段标签,所以像:

Labels:  English: _____FOO IN ENGLISH____ 
       German: _____FOO IN GERMAN_____ 
       Russian: _____FOO IN RUSSIAN____ 

我也想确保所有我的选择/支持语言显示 - 即使他们目前没有任何价值。

因此,这似乎是一个DataTransformer适当的地方,但尝试我可能无法得到这个概念范围内的Form类。似乎试图转换集合类型的数据比简单的文本类型更难(或不可能)。

我已经克服了这个问题,作为一种解决方法,在将控制器中的数据提交给表单之前以及在持久化之前处理表单之前,对其进行转换。例如

$this->transformTranslations($fooEntity); 
    $form = $this->createForm(FooType::class, $fooEntity); 
    $form->handleRequest($request); 
    if ($form->isSubmitted() && $form->isValid()) { 
     $fooEntity = $form->getData(); 
     $this->reverseTransformTranslations($fooEntity); 
     $this->getDoctrine()->getManager()->persist($fooEntity); 
     $this->getDoctrine()->getManager()->flush(); 
    ... 

我想知道如果任何人有一个更好的方法(如怎样使用正常的数据或模型变压器)。我似乎无法在网上找到有关使用数据转换器与集合类型的更多信息。 TIA!

回答

0

因此,我了解到我需要将我的两个需求分解成不同的解决方案。首先,我创建了一个新的表单类型,而不是用我所用系统默认的文本类型:

$builder 
     ]) 
     ->add('labels', CollectionType::class, [ 
      'entry_type' => TranslationType::class 
     ]) 

这个类是非常简单,只是一个普通TextType的扩展:

class TranslationType extends AbstractType 
{ 
    /** 
    * @var LocaleApiInterface 
    */ 
    private $localeApi; 

    /** 
    * TranslationType constructor. 
    * @param LocaleApiInterface $localeApi 
    */ 
    public function __construct(LocaleApiInterface $localeApi) 
    { 
     $this->localeApi = $localeApi; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     $view->vars['label'] = array_search($view->vars['name'], $this->localeApi->getSupportedLocaleNames()); 
    } 

    public function getParent() 
    { 
     return TextType::class; 
    } 
} 

这满足标签问题。其次,要确保我有所有支持的语言环境中我的数据,我用FormEventListener:

$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { 
     $supportedLocales = $this->localeApi->getSupportedLocales(); 
     $data = $event->getData(); 
     $labels = $data['labels']; 
     foreach ($supportedLocales as $locale) { 
      if (!array_key_exists($locale, $labels)) { 
       $labels[$locale] = $labels['en']; 
      } 
     } 
     $data['labels'] = $labels; 
     $event->setData($data); 
    }); 

这增加了所需的关键数据,如果它们不存在。

0

我没有亲自使用过一种学说数组值,但是 可以定义一个“默认” form class为您的每个翻译选项,如下所示:

的appbundle \表格\ LanguageStringEditorType.php

class LanguageStringEditorType extends AbstractType { 
    public function buildForm(FormBuilderInterface $builder, array $options) { 
     $builder 
      ->add('en', TextareaType::class, ['label' => 'English']) 
      ->add('de', TextareaType::class, ['label' => 'German']) 
      ->add('ru', TextareaType::class, ['label' => 'Russian']) 
     ; 
    } 
} 

如果保持命名(“恩”,“德”和“RU”)与您的数据数组的键名,例如具有(主义)实体是这样的:

的appbundle \实体\ LanguageString.php

class LanguageString { 
    private $identifier; 
    private $translations; // this is the doctrine array type 
          // however I didn't feel like setting up a database for this 
          // test so I'm manually filling it see the next bit 

... Getter and setter things ... 

,并创建一个类型,以及:

的appbundle \表格\ LanguageStringType。PHP

class LanguageStringType extends AbstractType { 
    public function buildForm(FormBuilderInterface $builder, array $options) { 
     $builder 
      ->add('identifier') 
      ->add('translations', LanguageStringEditorType::class, ['label' => 'Translations']) 
     ; 
    } 
} 

我们可以在控制器

$data = new LanguageString(); 
// fill some dummy content (not using database).. 
$data->setIdentifier('hello_world'); 
$data->setTranslations([ 
    'en' => 'Hello world!', 
    'de' => 'Hallo Welt!', 
    'ru' => 'Привет мир' 
]); 

$form = $this->createForm(LanguageStringType::class, $data); 

return $this->render('default/index.html.twig', [ 
    'form' => $form->createView() 
]); 

使用,其余的魔法造成的,无需变压器。数据放置在表单域中。并在使用handleRequest时设置为实体。请记住,数据键值与表单构建器名称相同。

作为奖励,您已经定义了LanguageStringEditorType类中的所有默认语言字段,是否填充。

+0

感谢您花时间回答!对此,我真的非常感激!我想我需要一些更灵活的东西。我找到了一个答案,我将在下面分享: – craigh