Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [SF][SF3] Data transformer
netvalue
post 11.04.2018, 09:16:34
Post #1





Grupa: Zarejestrowani
Postów: 199
Pomógł: 2
Dołączył: 9.06.2008

Ostrzeżenie: (0%)
-----


Zastanawiam się jak podejść do takiego tematu: mam dwie entity:
Product , ProductDocument z relacją ManyToOne (zdjęcia do produktu).

Uzytkownik dodaje produkt (form builder) w tym formularzu mam odrazu pole typu hidden w którym wrzucam nazwy plików (document) które wgrał przez plugin ajaxowy. Czyli wartość tego pola będzie przykładowo:

  1. "plik1.jpg;plik2.jpg;plik3.jpg"


Potrzebuje z powyższego stringa wyciągnąć nazwę pliku , stworzyć obiekt ProductDocument i powiazać z Product.
W obecniej chwili ten formularz zapisuje mi Product , natomiast ProductDocument tez dodaje się ale bez powiazania z Product, ponadto dodaj mi pełną wartość do nazwy ""plik1.jpg;plik2.jpg;plik3.jpg"" zamiast każdy oddzielnie. Wiem że trzeba użyć explode(';'.$wartosc) ale nie wiem gdzie


w ProduktForm mam
  1. class ProductFormType extends AbstractType
  2. {
  3.  
  4. private $transformer;
  5.  
  6. public function __construct(DocumentTransformer $transformer)
  7. {
  8. $this->transformer = $transformer;
  9. }
  10.  
  11. public function buildForm(FormBuilderInterface $builder, array $options)
  12. {
  13. $builder
  14. ->add('catalogNo', ChoiceType::class, array(
  15. 'attr' => array('class' => 'select2live','required'=>'required'),
  16. 'choices'=>array()
  17. ))
  18. ->add('productDocument', HiddenType::class)
  19. ->add('purchasedAt', DateType::class, [
  20. 'widget' => 'single_text',
  21. 'attr' => ['class' => 'js-datepicker'],
  22. 'html5' => false,
  23. ]);
  24.  
  25. $builder->get('productDocument')->addModelTransformer($this->transformer);
  26.  
  27. }
  28.  
  29. public function configureOptions(OptionsResolver $resolver)
  30. {
  31. $resolver->setDefaults([
  32. 'data_class' => 'AppBundle\Entity\Product'
  33. ]);
  34. }
  35.  
  36. public function getBlockPrefix()
  37. {
  38. return 'app_bundle_product';
  39. }
  40. }


DataTransformer.php
  1.  
  2. class DocumentTransformer implements DataTransformerInterface
  3. {
  4.  
  5. private $em;
  6.  
  7. public function __construct(EntityManagerInterface $em)
  8. {
  9. $this->em = $em;
  10. }
  11.  
  12. public function transform($document)
  13. {
  14. // TODO: Implement transform() method.
  15. if(null == $document)
  16. {
  17. return '';
  18. }
  19. return $document->getId();
  20. }
  21.  
  22. public function reverseTransform($files)
  23. {
  24. if(!$files)
  25. {
  26. return;
  27. }
  28. $document = new ProductDocument();
  29. $document->setName($files);
  30. return $document;
  31. }
  32. }

Go to the top of the page
+Quote Post
LowiczakPL
post 11.04.2018, 10:04:52
Post #2





Grupa: Zarejestrowani
Postów: 313
Pomógł: 21
Dołączył: 3.01.2016
Skąd: Poznań

Ostrzeżenie: (0%)
-----


1. Uważam że pole Hidden jest zbędne.
Dodajesz zdjęcia za pomocą AJAXa więc od razu powinno być przypisanie do Produktu.

2. Pole ze zdjęciami jest Kolekcją więc transformer powinien zmieniać string na kolekcję i odwrotnie, \
nie obchodzi cię nic więcej bo Symfony zajmie się zapisem .

3. Ale jeśli chcesz na siłe mieć to pole w tej formie to przykładowo w kontrolerze/menadżerze możesz wyciągnąć dane z pola zdjęcie, tak jak napisałeś explode i przypisać pliki do produktu np.

  1. foreach ($pliki as $plik){
  2. $product->getDocuments()->add($plik);
  3. }


--------------------
Poszukuję zleceń najlepiej w Symfony, Laravel, ... PHP, MySQL, Back-End, Front-End, mogę pomóc też z Unity
Go to the top of the page
+Quote Post
netvalue
post 11.04.2018, 11:27:57
Post #3





Grupa: Zarejestrowani
Postów: 199
Pomógł: 2
Dołączył: 9.06.2008

Ostrzeżenie: (0%)
-----


ok ale jak bym zastosował się do Twoich rad z pkt 1
To jak mam przypisać zdjęcia do produktu skoro produkt jeszcze nie jest zapisany ?
Go to the top of the page
+Quote Post
Pilsener
post 14.04.2018, 21:45:30
Post #4





Grupa: Zarejestrowani
Postów: 1 577
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


Wystarczy użyć standardowej kolekcji:
https://symfony.com/doc/current/reference/f...collection.html

Nie trzeba żadnych pól typu hidden czy data transformerów, robisz pole formularza typu "MyFile", jak klikasz "dodaj zdjęcie" to JS tworzy nowe pole na podstawie prototype (jest nawet gotowy JS w dokumentacji)
Można tez użyć standardowego pola typu file, ale własne jest lepsze bo można od razu tam wrzucić np. miniaturkę fotki, dodatkowy checkbox "usuń zdjęcie", jakiś własny event listener itp.
Tego typu rozwiązania (np. dodawanie wielu adresów do jednego usera) są w Symfony dość oklepane - wystarczy dokumentacja i trochę praktyki.

A jak chcesz robić po swojemu to nie mieszaj do tego formularzy Symfony, bo szkoda czasu na tego typu protezy czy workaroundy.
Go to the top of the page
+Quote Post
netvalue
post 16.04.2018, 15:17:27
Post #5





Grupa: Zarejestrowani
Postów: 199
Pomógł: 2
Dołączył: 9.06.2008

Ostrzeżenie: (0%)
-----


ok zrobiłem z CollectionType i teraz mam tak że dodaje mi produkt i zdjęcia ale zdjęcia nie są powiązane z produktem w którym były dodawane, (brak jest uzupełnionego product_id)

productForm.php mam tak:

  1. $builder->add('productDocument', CollectionType::class,array(
  2. 'entry_type' => ProductDocumentFormType::class,
  3.  
  4. 'allow_add' => true,
  5. 'allow_delete' => true,
  6. 'by_reference' => false,
  7. 'label' => 'Gallery',
  8. 'required' => true
  9. ))


productDocumentForm.php

  1. $builder->add('name')
  2. ->add('filename')
  3. ->add('isDocumentAssembly');


enityty product.php:
  1. /**
  2.   * @ORM\OneToMany(targetEntity="AppBundle\Entity\ProductDocument", mappedBy="product",cascade={"persist", "remove"})
  3.   */
  4. private $productDocument;


entity productDocument.php"
  1. /**
  2.   * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Product", inversedBy="productDocument",cascade={"persist"})
  3.   */
  4. private $product;
Go to the top of the page
+Quote Post
Pilsener
post 17.04.2018, 07:07:34
Post #6





Grupa: Zarejestrowani
Postów: 1 577
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


To zobacz jeszcze to:
https://symfony.com/doc/current/form/form_collections.html

Ciebie powinien szczególnie interesować fragment Doctrine:
Cytat
Cascading Relations and saving the "Inverse" side


I trzeba starać się samemu sobie radzić, jest debug tool, można tam zobaczyć request, co jest w formularz, czy encje są dobrze zmapowane i tak dalej.
ProductDocumentForm powinien zwracać encję ProductDocument, to też trzeba sprawdzić. Debugger wszystko powie.
Go to the top of the page
+Quote Post
netvalue
post 17.04.2018, 10:01:30
Post #7





Grupa: Zarejestrowani
Postów: 199
Pomógł: 2
Dołączył: 9.06.2008

Ostrzeżenie: (0%)
-----


Dziękuję za pomoc smile.gif jesteś wielki
btw. brakowało mi czegoś takiego smile.gif

  1. public function addProductDocument(ProductDocument $productDocument)
  2. {
  3. $productDocument->setProduct($this);
  4. $this->productDocument->add($productDocument);
  5. }
  6.  
  7.  
  8. public function removeProductDocument(ProductDocument $productDocument)
  9. {
  10. $this->productDocument->removeElement($productDocument);
  11. }

Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 15.08.2018 - 15:32