Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Symfony][Symfony2][Symfony3]Jak wywołać funkcje __clone() w Symfony 3?
Forum PHP.pl > Forum > PHP > Frameworki
wluczykuj
Cześć, mam takie pytanie :

Potrzebuje sklonować/skopiować rekord w bazie danych za pomocą np. przycisku w aplikacji . W danym kontrolerze zrobiłem funckje private function cloneAction(Grid $grid) , tylko z racji, że nie jestem w tym biegły nie wiem jak wywołać ją na stronie żeby po przyciśnięciu przycisku dany rekord mi się skopiował. Zależy mi aby przycisk [kopiuj] pojawił się na wygenerowanej stronie np show.html.twig . Czy mógłby ktoś mi w tym pomóc, doradzić ? To kod jaki mam, czy w ogole on jest w porzadku ?

EDIT: nalezy użyć metody __clone()? jesli tak to w jaki sposob ?

  1. private function cloneAction(Grid $grid){
  2. $oldGrid= ($grid);
  3. $newGrid= clone $oldGrid;
  4.  
  5. return $this->render('grid/show.html.twig', array(
  6. 'newGrid' => $newGrid
  7.  
  8. ));
  9. }
ohm
__clone używasz w konkretnym entity.
Ogólnie po sklonowaniu danego obiektu musisz go jeszcze zapisać w bazie (przez persist/flush)
wluczykuj
głównie chodzi mi o cos takiego , przestawilem to obrazowo:

http://symfonylab.pl/forum/index.php?actio...ttach=166;image
Pilsener
1. Nie trzeba klonować. Poza tym to jest słabe, bo nie klonuje ani dzieci, ani tym bardziej relacji, czyli jak masz obiekt A a pod nim B i C gdzie B ma relację do C, to sklonowany obiekt A2 nie będzie zawierał B2 i C2, tylko B i C. Do tego problemy z wydajnością (obiekty bazy danych są zazwyczaj dość rozległe) czy stabilnością (jeden rekord w bazie to powinien być jeden obiekt).
2. Kopiując encję musimy mieć na uwadze dwie rzeczy:
- które obiekty chcemy powielić a które nie
- które relacje chcemy podmienić a które nie

Przykład: obiekt A składa się z B i C, przy czym B ma relację do C. Zalożenia:
- powielamy A, B i C na A2, B2 i C2
- relacja w B2 wciąż wskazuje na C, więc zmieniamy to relację na C2
Czyli będą dwa etapy:
1. Powielanie wybranych obiektów
2. Zmiana relacji w wybranych obiektach

Etap pierwszy możemy zautomatyzować korzystając z kaskadowości:
http://docs.doctrine-project.org/projects/...sociations.html

Czyli jak mamy np. Menu gdzie będzie relacja do Url a w "cscade" ustawimy "detach" to:
  1. $entityManager->detach($menu);

Spowoduje, że zarówno Menu, jak i Url będą jakby "odłączone" od bazy, nie są one już obiektowymi odpowiednikami rekordów w bazie lecz "zwykłymi" obiektami i próba ich np. flushowania zwróci exception.
Można natomiast:
  1. $entityManager->persist($menu);

I teraz znów, możemy ustawić kaskadowość tak, żeby Url został dodany od razu z Menu

Natomiast etap drugi musimy zrobić ręcznie, czyli dotrzeć do odpowiednich obiektów i wywołać odpowiednie settery.
wluczykuj
a) które obiekty chcemy powielić a które nie

chcę powielić wszystko , tylko tak żeby były inne identyfikatory id, coś na zasadzie generowania pełnego wzrozu tabeli z wypełnionymi danymi gotowymi do edycji



b ) które relacje chcemy podmienić a które nie

tego nie rozumiem, ale to chyba wyjaśnia ta linijka:
- relacja w B2 wciąż wskazuje na C, więc zmieniamy to relację na C2 , tylko jak ?


Przyznam całkiem szczerze, że nie jestem w tym taki biegły i tez nie chcę aby to zabrzmiało że oczekuje gotowego rozwiązania (bo nawet mój przykład który przytoczyłem jest poglądowy i różni sie nieco od oryginału), ale czy byłbyś w stanie mi pomóc poskładać ten kod od podstaw? bo o ile Twoje wskazówki są dla mnie w miarę zrozumiałe to chyba to przekracza moje umiejętności, a bardzo potrzebuje się tego nauczyć.

sądzę , że należałoby zacząć od akcji w kontrolerze GridController, a później wywołanie tejże akcji przyciskiem na stronie i teraz własnię mam pytania:

[pytania]
jak te akcję zbudować?
jak ją wywołać przyciskiem?


jeszcze raz pragnę zaznaczyć, że nie chcę dostac bezmyślnie gotowca, ale chyba bez przykładu od podstaw do końca się tego nie nauczę, mogę liczyć na pomoc ? i w ogole dziekuję za odpowiedz smile.gif


EDIT: jeszcze była mowa o stworzeniu serwisu ktory otrzyma kolekcje encji , czy to dobry kierunek questionmark.gif?
"i stworzy sobie gotowe obiekty z wypełnionymi danymi a następnie zrobić persist i flush. Bo dane będą te same, ale identyfikatory nie."

doszukałem się tego zagadnienia w dokumentacji, czy to się nada ?

https://symfony.com/doc/current/service_container.html
Pilsener
1. Jak stawiasz "goły" framework to już masz default controller z gotową akcją, skopiować, podmienić routing, podlinkować przycisk - 5 minut, w dokumentacji jest to dobrze opisane, jeśli masz tu braki to powinieneś zacząć od podstaw.
2. Twój kod kopiowania encji na początek powinien się ograniczyć do:
  1. $entityManager->detach($entity);
  2. $entityManager->persist($entity);
- i powinieneś przeanalizować jak to działa, praca z encjami jest ładnie opisana:
http://symfony.com/doc/current/doctrine.html
3. "chcę powielić wszystko" - czyli całą bazę danych? Bo prawie każdy rekord ma "createdBy", więc powielisz też usera, jak powielisz usera to i wszystkie rekordy które on stworzył, potem relacje z tych rekordów i w ten sposób powielisz całą bazę danych smile.gif Dlatego trzeba wiedzieć dokładnie, jakie encje mają być "detach" bo nawet, jeśli dziś nie ma żadnej relacji to ktoś ją może w przyszłości dodać, rozbudowując funkcjonalność aplikacji.
4. Robienie serwisów i wywoływanie ich w kontrolerach jest dobrym pomysłem

Spróbuj po prostu napisać kawałek kodu i zobacz jak to działa.
wluczykuj
Teraz jeszcze napotkalem taki sposob , czy to by było dobre? tylko jak to uzupelnic?

napisałeś ze moj kod ma sie ograniczac do :

  1. $entityManager->detach($entity);
  2. $entityManager->persist($entity);


czyli mam to jeszcze gdzies tu umieścic ? Staram sie to zrozumiec i jakoś poradzic sobie ale nie bardzo mi to wychodzi, w dobrą stronę podążam w ogole ?


(podeśle pastebina z dwoma przykladowymi encjami)

encja ktora ma byc kopiowana
http://pastebin.com/kYYhqXfe

encja ktora ma w sobie klucz obcy z powyzszej encji
http://pastebin.com/jTQtcBLn

kontroler
http://pastebin.com/g8EBeY1k


EDIT: to co zrobiłem teraz sam :

PlachtaController.php
-dodalem akcje cloneAction(Plachta $plachtum)
ponizej kod:

Akcja w kontrolerze:
  1. public function cloneAction(Plachta $plachtum){
  2.  
  3. $em = $this->getDoctrine()->getManager();
  4. $plachtas = $em->getRepository('AppBundle:Plachta')->find($plachtum);
  5. $cloneY = clone $plachtas;
  6.  
  7. //jak uzupelnić zeby moc to odpalić na stronie ? ? ?
  8.  
  9. }



Encja Plachta.php

  1. public function __clone(){
  2. if ($this->idPlachta) {
  3. $this->setIdPlachta(null);
  4. $this->x = clone $this->x; //co dac w miejsce x questionmark.gif?
  5. }
  6. }



Encja Przedmiot.php
  1. public function __clone(){
  2. if ($this->id) { //co dac w miejsce id ?
  3. $this->setId(null); //co dac w miejsce setId questionmark.gif
  4. }
  5. }

To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.