2017-08-17 10 views
1

fileTypeフィールドを持つエンティティのコレクションがある場合、フォームの更新を正しく処理する方法。私は Symfony upload docsに従って行動とリスナーを行いました。エンティティの作成は完璧に機能しますが、ファイルが選択されていないため、編集アクションは失敗し、symfonyはコレクションフィールドをファイルフィールドにnull値で更新しようとします。symfony 3フォームコレクションエンティティfiletypeフィールドeditAction

AppBundle\Entity\Product: 
    type: entity 
    # ... 
    oneToMany: 
     images: 
      targetEntity: Image 
      mappedBy: product 

フォーム:

// AppBundle\Form\ProductType 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     // ... 
     ->add(
      'images', 
      CollectionType::class, 
      [ 
       'entry_type' => ImageType::class, 
       'allow_add'  => true, 
       'allow_delete' => true, 
       'by_reference' => false, 
       'entry_options' => ['label' => false], 
       'label_attr' => [ 
        'data-feature' => 'editable', 
       ], 
      ] 
     ); 
} 

// AppBundle\Form\ImageType 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('file', FileType::class, ['required' => false]) 
     // another fields... 
} 

アクション:私の意見では

// AppBundle\Controller\Backend\ProductController 
// ... 
public function editAction(Request $request, EntityManagerInterface $em, Product $product) 
{ 
    $editForm = $this->createForm('AppBundle\Form\ProductType', $product); 
    $editForm->handleRequest($request); 

    $originalImages = new ArrayCollection(); 

    foreach ($product->getImages() as $image) { 
     $originalImages->add($image); 
    } 

    if ($editForm->isSubmitted()) { 
     if ($editForm->isValid()) { 
      foreach ($originalImages as $image) { 
       if (false === $product->getImages()->contains($image)) { 
        $em->remove($image); 
       } 
      } 

      $em->flush(); 

      $this->addFlash('success', 'Success'); 
     } else { 
      $this->addFlash('warning', 'Error saving'); 
     } 

     return $this->redirectToRoute('backend_product_edit', ['id' => $product->getId()]); 
    } 
} 
// ... 

私はどこかの空のファイルのフィールドの設定を解除する必要がありますが、私がどこかわからない...(

PS VichUploaderBundleのようなバンドルを使うことができることは知っていますが、どのように動作するのか、そして私がwronをやっていることを理解したいと思いますg! P.P.S.私の英語には申し訳ありません

答えて

1

変更IMAGETYPEフォームは完全に私の問題

// AppBundle\Form\ImageType 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('file', FileType::class, ['required' => false, 'data_class' => null]]) 
     // another fields... 
    ; 
    // adding this forces to use old file if there is no file uploaded 
    $builder->get('file')->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { 
     if (null === $event->getData()) { 
      $event->setData($event->getForm()->getData()); 
     } 
    }); 
} 
1

1週間前に同じ問題がありました。この問題について多くのスレッドを読んだら、セキュリティ上の理由から、フォームの "ファイルフィールド"をあらかじめ入力することはできないようです。

私が実装したシンプルなソリューション:

をあなたの「editAction方法」で:フォーム「編集」をレンダリングする前に、ユーザーのセッションで現在のファイルフィールドの値を割り当てます。

ユーザーが「更新」フォームを送信すると、更新前のイベント(例としてdoctrineライフサイクル)を使用してセッション内のファイル名を検索し、それらをエンティティに割り当ててから永続化することができます。

Basicalyあなたは私の場合は教義の関係は1つのニュース1つの画像ファイルを持っていた。このような何か(私はあなたのロジックにそれを適応させる必要が私のエンティティのためのコードを与える)

を行う必要があります。あなたのeditActionで

protected function editNewsAction() 
{ 
    //some code 

    if (!$response instanceof RedirectResponse) 
    { 
     $entityId = $this->request->query->get('id'); //the id of my entity was in the query string in my logic 

     $repo = $this->getDoctrine()->getManager()->getRepository('AppBundle:News'); 
     $oldEntity = $repo->findOneBy(['id' => $entityId]); 
     $oldEntityImage = $oldEntity->getImage(); // I had oneToOne Relation so adapt it for your own logic 

     $session = $this->get('session'); 
     $session->set('newsImage', $oldEntityImage); 
    } 

    // some code 
} 

そして、更新前のイベントで:

protected function preUpdateNewsEntity($entity) 
{ 
    //some code 

    if (!$entity->getImageFile()) 
    { 
     $session = $this->get('session'); 

     $entity->setImage($session->get('newsImage')); 

     //don't forget to remove the value in session 
     $session->remove('newsImage'); 
    } 

    //some code 
} 

私は、これはあなたを助けることを願っています。

+0

私はこのような何かについて考えを解決しますが、 'FormEvents :: PRE_SET_DATA'イベントリスナーを持ちます。元のオブジェクトを取得し、提出されたフィールドを確認する可能性があります。詳細については、[docs](https://symfony.com/doc/current/form/dynamic_form_modification.html) – Vladimir

+0

のリンクをご覧ください。私はあなたが絶対に正しいと思います。 FormEventsも同様に使用できます。 – Mz1907

関連する問題