2017-06-02 121 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