Laravel, podobne modele - dziedziczenie?

0

Cześć,

chciałbym Was zapytać jak w Laravel najlepiej jest rozwiązać problem dziedziczenia (i czy to słuszny pomysł na rozwiązanie problemu?), oraz jak to najwydajniej zrobić.

Żeby nie wchodzić w zbędne szczegóły posłużmy się przykładem potworków :)

Wszystkie potwory w aplikacji mają atrybuty wymiary, waga, żywioł, lokalizacja, okres występowania

Teraz zależnie od żywiołu potwora będę tworzył żywiołaki, ale każdy może mieć zupełnie inne atrybuty i funkcje:
-wodne będą miały atrybut czy słono, czy słodkowodne, funkcje gaszenia pożaru, maksymalna głębokość zanurkowania,
-powietrzne udźwig materiału w locie, mogą zrobić podmuch i rodzaj pokarmu jaki spożywają...
i tak dalej i tak dalej...

Do tego w danej lokalizacji może występować tylko jeden potwór z danego żywiołu, więc tworząc nowego muszę sprawdzić czy nie ma już jakiegoś o danym żywiole np. w lokalizacji Azeroth, a nawet jak był to może już wymarł (okres wystepowania) i może wtedy przyjść następny na jego miejsce (tutaj pojawia się też problem archiwizacji danych, ponieważ chciałbym wiedzieć w jakim okresie i co tam występowało).

To co mi przychodzi do głowy to stworzyć klasę/model główny potwor i wrzucić to do jednej tabeli razem ze wszystkimi wspólnymi atrybutami, a dodatkowo status czy wymarł czy nie. Następnie połączyć to w relacji polimorficznej z każdym kolejnym modelem odpowiedzialnym za dany żywioł.
Teoretycznie w ten sposób wszystko będzie działało.

Pytanie jednak czy takie rozwiązanie będzie optymalne? Z tego co pamiętam jeszcze pisanie gierek w Javie to jak nic prosi się o zaimplementowanie jakiejś formy dziedziczenie po potworze dla każdego żywiołu. Jak to wtedy rozpisać w Laravel z uwzględnieniem migracji? Czy w ogóle rozpisywać, jeżeli pracujemy właśnie na modelach z odwzorowaniem wszystkiego w bazie danych, tak żeby trzymać się jako takiej normalizacji?

Uprzedzając uwagi - nie chce pisać gry w Laravel, po prostu taki mi przyszedł motyw, żeby ubrać w słowa bardziej złożony problem :P

Chodzi mi głównie o ogólne koncepcje przy tego typu modelach i prawidłowym podejściu, bo napisać da się to na pewno jeszcze na kilka sposobów.

Nie wiem czy zrozumiale rozpisałem problem, w razie czego pytajcie, a uzupełnię brakujące informacje.

0

Laravel i gry komputerowe?? Pierwsze slysze..., no chyba ze backend w Laravel, a gra we frontend JavaScript / JQuery

0

Co ten temat ma wspólnego z Laravel?
Laravel wprowadza jakiś inny schemat OOP niż ten obecny w PHP?
Jeśli nie to narysuj diagramy dziedziczenia - tak będzie łatwiej zrozumieć o co pytasz.

0

No właśnie mi chodzi jak to najwydajniej ugryźć Laravelem.

Może za bardzo chciałem to rozpisać... Można to w sumie jeszcze bardziej uogólnić do tego, jak rozpisać modele, które maja kilka wspólnych i zależnych od siebie pól, jednak różne funkcje i kilka atrybutów dodatkowych.

Jeżeli to wciąż za mało jasne to jutro na spokojnie coś rozpisze i dorzucę.

0

Ponadto Laravel wykorzystuje wzorzec MVC. Trudne w przypadku podzialu aplikacji na modele, widoki i kontrolery odwzorowac rzeczywistosc domenowa. W klasie Potwor, oprocz atrybutow sa tez metody, ktore pelnia po czesci role modelow, widokow i kontrolerow.
Zastanawiam sie, jak sie ma odwzorowanie rzeczywistosci w modelowaniu obiektowym, kiedy framework z gory narzuca wzorzec MVC ?

0

No właśnie mi chodzi jak to najwydajniej ugryźć Laravelem.

Chyba jednak wciąż za bardzo się rozpisałem... Można to w sumie jeszcze bardziej uogólnić do tego, jak rozpisać modele, które maja kilka wspólnych atrybutów i funkcji, jednak każdy z nich potrzebuje też posiadać swoje własne, unikatowe atrybuty i metody.

Od tych części wspólnych zależna jest istnienie kolejnych obiektów.

Wszystko natomiast później trzeba zmieścić w bazie danych.

Jak wspomniałem, nie buduje gry, oraz na pałę jakieś rozwiązania nawet napisałem, które wstępnie działa.
Ciekawi mnie jednak ogólna teoria jak powinno wyglądać najoptymalniejsze/najlepiej najelastyczniejsze rozwiązanie, i ewentualne linki do źródeł wiedzy gdzie mógłbym poczytać na temat takich problemów.

Jeżeli to wciąż za mało jasne to jutro na spokojnie coś rozpisze i dorzucę.

0

Moim skromnym zdaniem - już nie zagłębiając się w ten konkretny przypadek - jeśli zależy Ci na poprawnym modelu obiektowym zagadnienia, to po prostu zamodeluj sobie to w czystych klasach. Wrzuć je do katalogu np. src, daj namespace np. \Masakra\Potwory, ustaw to w composer.json. Jak już będzie hulać z poziomu cli/testów, to stwórz sobie dowolny model w bazie danych, z którego da się budować (nawet ręcznie) instancje klas potworków, budować mapę, robić raporty etc. Kontrolowana denormalizacja danych w dzisiejszych czasach to powszechne zjawisko, podobnie jak kilka źródeł danych sklejanych w aplikacji (klasycznie np. RDBMS + NoSQL). Nie myśl w kategoriach tabela -> klasa.

Pomostem między tym, co wyciągniesz z bazy (przez Eloquent, query builder i inne) a logiką Twoich klas powinny być repozytoria i ew. fabryki.

0

A i jeszcze odnośnie:

Można to w sumie jeszcze bardziej uogólnić do tego, jak rozpisać modele, które maja kilka wspólnych atrybutów i funkcji, jednak każdy z nich potrzebuje też posiadać swoje własne, unikatowe atrybuty i metody.

Prosta klasa bazowa + kompozycja.

Rozważyłbym przeniesienie takich rzeczy jak akcje/umiejętności/zdolności/zaklęcia (jak to tam nazywasz) do osobnych klas (mówię o czystych klasach - POPO, a nie modelach Eloquenta). I wtedy za pomocą jakiejś \Masakra\Potwory\MonsterService::summonOceanDragon() budowałbyś instancję OceanDragon, który do jego kolekcji zdolności przyjmowałby instancje odpowiednich klas zdolności.

W tym momencie dochodzisz już do poziomu wobec którego klasyczny relacyjny model w "bazce" i wygenerowane automatycznie modele już nie przystają. Te modele mogą Ci uprzyjemnić wyciąganie/zapis/monitorowanie danych i ich mapowanie na Twoje obiekty, ale na tym właściwie koniec.

0

To skrajna niedorzecznosc robic cos takiego w Laravel.

0

Nie chce robić miliarda klas, potworów i zależności, chciałem tylko zapytać jak tego typu problemy można i powinno się rozwiązywać za pomocą Laravel, bo ciężko mi uwierzyć, że moje poytanie odnośnie wielu wspólnych pól kilku klas jest jakieś wyjątkowe i wierzę, że nie jedna ciekawa aplikacja działa w ten sposób. A nawet jeżeli nie w ten, to widocznie w jakiś sposób sa podobne problemy rozwiązywane i stąd pytanie o wasze doświadczenia w tej sprawie, albo ciekawe linki lub słowa kluczowe do poczytania na ten temat.

Jak wspomniałem na początku innym rozwiązaniem niż łączenie wszystkiego w relacjach polimorficznych na modelach to stworzyć jakaś klase bazową i dziedziczyć po niej pewne atrybuty i wspólne założenia przy budowaniu wszystkich "żywiołaków" w tym wpadku. Jeżeli dobrze rozumiem, to to o czym myślałem to pokrywa się mniej więcej z rozwiązaniem Skromnego Ogrodnika.

Druga kwestia nad jaką się zastnanawiałem co ciągłe budowanie obiektów z bazy opartych na kilku tabelach. Czy jest to najoptymalniejsze rozwiązanie, a jak nie to w jaki sposób podejść do budowy bazy danych w podobnym przypadku, na co poniekąd Ogrodnik też udzielił już odpowiedzi za co wielkie dzięki, że poważniej podszedłeś do pytania i nieco się rozpisałeś :)

Wybaczcie też jeżeli to są głupie pytania, po prostu jestem totalnym samoukiem i chciałem poznać podejście bardziej doświadczonych osób, bo później jak tak człowiek na siłę wszystko sam chce napisać, to albo wymyśla koło od nowa, albo kończy się to legendami i opowieściami o spaghetti.

0

Cały czas podtrzymuję to, co napisałem, ale skoro tak się upierasz przy Larvie, to może Tobie chodzić o np. single-table-inheritance. Nie mam doświadczenia w Laravelu, ale np. w Yii - które ma podobną implementację ActiveRecord jak Laravel - robi się to tak, że masz jedną tabelę "potwory" i jakąś kolumnę, która mówi, jaki to rodzaj potwora. Generujesz sobie bazowy model na podstawie tabeli np. Potwor i ręcznie dorabiasz model Smok extends Potwor, który ma coś takiego jak "defaultScope" i w nim ustawia np. $this->type = 1. Obok robisz Hipogryf extends Potwor i w defaultScope ustawiasz $this->type = 2; i tak dalej.

Framework zadba, że wszystkie metody typu Hipogryf::find() i pokrewne będą automatycznie doklejać type = 2 do zapytań. Działa to sprawnie, problemy są przy różnych automatycznych joinach między modelami, ale to już zależy od jakości całego ActiveRecord w danym frameworku.

Nie wiem, czy się zbliżyłem do Twoich rozważań, ale starałem się pomóc ;).

0

No to chyba to samo co w Laravel relacje polimorficzne.
Czyli np. w tabeli Potwór mam kolumnę żywiołak_type oraz żywiołak_id określającą, do którego modelu żywiołaka należa konkretne informacje,a później mogę się między nimi dowolnie odwoływać i je wyszukiwać np.

//Wyszukaj wszystkie wodne potrwory z danej lokalizacji
$azeroth = Potwor::where(['city', 'Azeroth'], ['żywiołak_type', 'water')->get()

//Wyszukaj wśród smokow Azor i sprawdz jego lokalizacje:
$azor = Smok::where('name', 'Azor')->first();
$azor->potwor->city 

//Edytujac właściwości i funkcje modelu możemy oczywiście później używac skrótów typu:
$azor->city
//lub
$potwor = Potwor::find(1) // wyciągamy potwor o id=1 i atakujemy
$potwor->attack($enemy)

Czyli jak wspomniałem teoretycznie rozwiązujemy większość postawionych tutaj problemów, a znaczną część rzeczy i tak robi za nas FW. Jedynie chodziło mi o słuszność takich rozwiązań i czy nie ma przypadkiem lepszych sposobów:P

1 użytkowników online, w tym zalogowanych: 0, gości: 1