
01 Kwi Encje doctrinowe i relacje – praktyczne wykorzystanie
Przyszedł czas na kolejną część cyklu o encjach doctrinowych. W ostatnim poście poznałeś już podstawy jak używać Doctrina. Wiesz jak konfigurować encje i podstawowe pola. Przyszedł czas osiągnąć kolejny poziom wtajemniczenia. W tym poście poznasz jak w Symfony 3 wykorzystać encje doctrinowe i relacje.
Encje doctrinowe i relacje
Bardzo rzadko występują modele baz danych, w których między tabelami nie występują relacje. Pokusiłabym się nawet, że w poważnych projektach nigdy nie znajdziemy takich modeli. Dlaczego? Bo nawet w świecie rzeczywistym ciężko znaleźć elementy, które nie wchodzą w relacje z żadnym innym elementem np. jabłko, rośnie na drzewie, które kwitnie, a kwiat zostaje zapylony przez pszczołę. Modelując taką sytuację, od razu widzimy, że zwykłe jabłko, będzie mieć relację z drzewem, kwiatem i pszczołą. Teraz Ty pomyśl, czy znajdziesz przykład elementu świata rzeczywistego, który nie posiada żadnych relacji? Jeśli tak to daj znać w komentarzu, podyskutujmy na ten temat, bo jest on bardzo ciekawy.
Podczas projektowania rozważałam dwa systemy bazy dancyh – MySQL oraz PostgreSQL.Oba te systemy zaliczamy do grupy relacyjnych baz danych. Oprócz nich wyróżniamy również bazy obiektowe i strumieniowe. Jednak to właśnie relacyjne są najbardziej rozpowszechnione i najczęściej używane. Mówiąc o relacyjnych bazach danych, ciężko nie wspomnieć o normalizacji. Są to zasady projektowania bazy danych, takie best practise. Jednak jest to bardzo obszerny temat na inny post.
Encje doctrinowe i relacje dają nam wiele możliwości definiowania stryktury, w zależności, jaki typ relacji chcemy zdefiniować, zrobimy to w różny sposób. Przykłady relacji będą pochodzić z projektu, który rozwijam w ramach konkursu Daj się poznać 2017. Kod znajdziesz na gihubie.
jeden – jeden
W moim projekcie relacja 1-1 zachodzi między użytkownikiem a jego adresem (user-userAdress). Ta relacja wyszła w tracie pracy. Jak to wygląda w kodzie? Już piszę. TargetEntity to encja, która wchodzi w relację, inversedBy i mappedBy mówią nam, które pole będzie odpowiadało drugiej stronie relacji. Cascade przy adresie określa, że przy usunięciu oraz utrwaleniu Usera nastąpi analogiczne działanie na adresie, określa to również onDelete = “CASCADE” po drugiej stronie relacji.
/** * @ORM\OneToOne(targetEntity="Backend\UserBundle\Entity\UserAddress", mappedBy="customer", cascade={"persist", "remove"}) * @var CustomerAddress */ private $address;
/** * @ORM\OneToOne(targetEntity="Backend\UserBundle\Entity\User", inversedBy="address") * @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE") * @var User */ private $user;
jeden – wiele
Jeden do wiele to chyba najczęściej używana relacja w moim projekcie i nie tylko np. wydarzenie może być przypisane do wielu grafików (event-charts), jeden organizator może organizować wiele wydarzeń (event-organizer). Elementy adnotacji są takie same jak w relacji 1-1 opisane powyżej.
/** * @ORM\ManyToOne(targetEntity="Backend\EventBundle\Entity\Organizer", inversedBy="events") * @ORM\JoinColumn(name="organizer_id", referencedColumnName="id") * @var Organizer */ private $organizer;
/** * @ORM\OneToMany(targetEntity="Backend\EventBundle\Entity\Event", mappedBy="organizer", cascade={"persist", "remove"}) * @var ArrayCollection|Events[] */ private $events;
wiele – wiele
To najbardziej skomplikowana relacja do skonfigurowania, ale oczywiście do zrealizowania. W moim przypadku zachodzi między wydarzeniem a jego ocenami (event-rate).
/** * @ManyToMany(targetEntity="Backend\EventBundle\Entity\Rate") * @JoinTable(name="events_rates", * joinColumns={@JoinColumn(name="rate_id", referencedColumnName="id")}, * inverseJoinColumns={@JoinColumn(name="event_id", referencedColumnName="id", unique=true)} * ) */ private $rates;
Jednak osobiście polecam stworzyć obiekt EventRate, który wchodzi w relacje jeden do wielu z wydarzeniem (event) i oceną (rate). Mamy większą kontrolę nad obiektami i tabelami.
Wszystkie przykłady są definiowane w adnotacji. Taki sam zapis możemy stworzyć w formie pliku yml dla każdej encji.
Kod, który podałam w przykładach, jeszcze w tym tygodniu pojawi się na githubie. Jeśli masz jeszcze jakieś pytania albo problemy w swoim projekcie napisz w komentarzu, chętnie pomogę, a może razem wpadniemy na jakieś rozwiązanie. Encje doctrinowe i i relacje między nimi to wiedza, którą powinien posiadać każdy programista chcący pracować z Symfony i Doctrinem.