Drukowana wersja tematu
Forum PHP.pl _ Frameworki _ [SF2][Symfony2][Symfony] Zapis encji w relacji
Napisany przez: damianooo 23.03.2016, 09:24:15
Czemu ponizszy zapis danych do bazy nie dziala ?
public function createAction(){
$type = new Type();
$match = new Match();
$match->getId(3);
$type->setNumberOfPoints(0);
$type->setUser($this->getUser());
$type->setMatch($match);
$em = $this->getDoctrine()->getManager();
$em->persist($type);
$em->flush();
}
Blad ktory otrzymyje jest nastepujacy:
A new entity was found through the relationship 'My\TyperkaBundle\Entity\Type#match' that was not configured to cascade persist operations for entity: . To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).
Relacje miedzy encja Type i Match mam taka:
// Type.php
class Type {
/**
* @ORM\ManyToOne(
* targetEntity = "Match",
* )
*
* @ORM\JoinColumn(
* name = "match_id",
* referencedColumnName = "id",
* onDelete = "SET NULL"
* )
*/
private $match;
Napisany przez: Crozin 23.03.2016, 10:13:40
Szybkie pytanie: co jest niezrozumiałe w treści wyjątku, który podaje Ci dwa możliwe rozwiązania problemu?
Napisany przez: uirapuru 23.03.2016, 10:41:06
szybka odpowiedz $em->persist($match) przed flushem powinno pomóc. btw: nie rób tego w kontrolerze.
Napisany przez: damianooo 23.03.2016, 11:39:34
Ok, dodalem:
$em->persist($match);
i udalo sie ... faktycznie nie doczytalem komunikatu, ktory przeciez jasno pisal co trzeba zrobic.
ale nie wiem czemu do bazy nie zostal dodany rekord do tabeli Type o match_id = 3 tylko o match_id = 41 (zainkrementowalo mi match_id )
a wskazalem przeciez w kodzie ze ma zostac dodany rekord z match_id = 3 :
public function createAction(){
$type = new Type();
$match = new Match();
$match->getId(3);
$type->setNumberOfPoints(0);
$type->setUser($this->getUser());
$type->setMatch($match);
$em = $this->getDoctrine()->getManager();
$em->persist($match);
$em->persist($type);
$em->flush();
}
Napisany przez: kapslokk 23.03.2016, 11:48:01
$match->getId(3);
get to nie set.
$match->setId(3);
Ale jesli ten match juz istnieje w bazie to chyba powinienes go pobrac
$match = $em->getRepository(...)->findOneById(3)
Napisany przez: ohm 23.03.2016, 11:49:32
Cytat(Crozin @ 23.03.2016, 10:13:40 )
Szybkie pytanie: co jest niezrozumiałe w treści wyjątku, który podaje Ci dwa możliwe rozwiązania problemu?
Podpowiadam
Kod
To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).
Napisany przez: damianooo 23.03.2016, 11:51:37
nie ma takiej metody w mojej encji Match jak setId()
to chyba nie tak sie robi ...
Tak - takie $match o ID = 3 juz istnieje dlatego chcialem pobrac getId()
rozumiem ze musze to zrobic tak:
$match = $em->getRepository(...)->findOneById(3)
i nie ma innej drogi
zastanawia mnie tylko dlaczego kolega wczesniej prosil/ostrzegal zeby zapisu nie robic w konrolerze
... rozumiem ze chodzi o ograniczenie linii kodu ?
Napisany przez: kapslokk 23.03.2016, 12:00:43
No bo tak jak Ci napisałem, nie powinieneś tego ustawiać ręcznie tylko pobrać z bazy istniejący rekord / zdać się na auto_increment;
getId() jak i cała reszta getterów służy do pobrania wartości z konkretnego obiektu, a nie obiektu z bazy na podstawie tej wartości.
Cytat
zastanawia mnie tylko dlaczego kolega wczesniej prosil/ostrzegal zeby zapisu nie robic w konrolerze smile.gif ... rozumiem ze chodzi o ograniczenie linii kodu ?
Nie mam pojęcia, ktoś mądrzejszy sie musi wypowiedzieć.
Napisany przez: Crozin 23.03.2016, 12:54:26
Cytat
ale nie wiem czemu do bazy nie zostal dodany rekord do tabeli Type o match_id = 3 tylko o match_id = 41 (zainkrementowalo mi match_id )
Zapewne dla właściwości @Id masz ustawione automatyczne generowanie wartości (@GeneratedValue(AUTO)). Wtedy Doctrine zignoruje ręcznie ustawioną wartość przez setId(x).
Cytat
nie ma takiej metody w mojej encji Match jak setId()
to chyba nie tak sie robi ...
Jeżeli decydujesz się na ręczne bądź półautomatyczne (np. przy pomocy sekwencji) nadawanie ID-ków, to taką metodę setId() jak najbardziej możesz czy wręcz musisz mieć. Generalnie nawet jeżeli ID-ki generowane są wyłącznie przez bazę danych metoda setId() wiele nie wadzi, a przy pisaniu testów może się przydać.
Cytat
zastanawia mnie tylko dlaczego kolega wczesniej prosil/ostrzegal zeby zapisu nie robic w konrolerze (IMG:style_emoticons/default/smile.gif) ... rozumiem ze chodzi o ograniczenie linii kodu ?
Liczba linii kodu jest bez znaczenia. Chodzi po prostu o to, że kontroler to nie miejsce dla ORM-a, który raczej powinien być użyty dopiero gdzieś głęboko w warstwie przetwarzania danych, czy właściwie dostępu do danych. Ale nie zawsze potrzebujemy takiej separacji kodu, na różne warstwy stąd Symfony udostępnia "łatwy" dostęp do Doctrine'a wewnątrz kontrolerów dziedziczących po Symfony\Bundle\FrameworkBundle\Controller\Controller.
Napisany przez: uirapuru 23.03.2016, 13:19:09
podpowiem: przypuśćmy, że chcesz dokładnie te samą operację wykonać w symfonowym commandzie. naturalnie, skopiujesz i przekleisz ten kod. co lepsi nawet rejestrują kontroler jako serwis i wywołują te akcje. Ale zawartość akcji Twojego kontrolera jest aplikacją samą w sobie, można jej fragment wydzielić i po prostu użyc: w kontrolerze, w commandzie, a co najwazniejsze - w teście
ps. spróbuj przetestować np. jednostkowo te akcje kontrolera.
ps2. bo testujesz, prawda?
ps3. przypuścmy sytuację, że pojawia się nowa niekompatybilna wstecz wersja frameworka LUB chcesz zmienić framework. Też kapa przy Twoim podejściu
Generalnie: jest wiele powodów, żeby tak nie robić, niewiele powodów by tak robić
Napisany przez: damianooo 23.03.2016, 13:43:19
ok dzieki za uwagi ... przemysle to sobie ... chce to robic dobrze wiec bede o tych uwagach pamietal.
Pozdrawiam
Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)