Tworząc aplikację w Laravel 4, po przeczytaniu książki T. Otwella o dobrych wzorcach projektowych w Laravel, znalazłem repozytoria dla każdej tabeli w aplikacji.
Skończyło się na następującej strukturze tabeli:
- Uczniowie: identyfikator, imię i nazwisko
- Kursy: identyfikator, imię i nazwisko, identyfikator nauczyciela
- Nauczyciele: id, imię
- Zadania: identyfikator, imię i nazwisko, identyfikator kursu
- Wyniki (działa jako punkt zwrotny między studentami i zadaniami): student_id, assignment_id, score
Mam klasy repozytorium z metodami wyszukiwania, tworzenia, aktualizowania i usuwania dla wszystkich tych tabel. Każde repozytorium ma model elokwentny, który współdziała z bazą danych. Relacje są zdefiniowane w modelu zgodnie z dokumentacją Laravel: http://laravel.com/docs/eloquent#relationships .
Podczas tworzenia nowego kursu wszystko, co robię, to wywoływanie metody create w repozytorium kursów. Ten kurs ma przypisane zadania, więc podczas tworzenia takiego kursu chcę również utworzyć wpis w tabeli wyników dla każdego ucznia na kursie. Robię to za pośrednictwem repozytorium przydziałów. Oznacza to, że repozytorium przydziałów komunikuje się z dwoma elokwentnymi modelami, z modelem przydziału i ucznia.
Moje pytanie brzmi: ponieważ ta aplikacja prawdopodobnie powiększy się i zostanie wprowadzonych więcej relacji, czy dobrą praktyką jest komunikowanie się z różnymi modelami Eloquent w repozytoriach, czy też powinno to być zrobione przy użyciu innych repozytoriów (mam na myśli wywoływanie innych repozytoriów z repozytorium przydziałów ) czy też należy to zrobić w modelach Eloquent razem?
Ponadto, czy dobrą praktyką jest używanie tabeli wyników jako punktu odniesienia między zadaniami a uczniami, czy też należy to zrobić gdzie indziej?
$a = $this->account->getById(1)
nie mogę po prostu łączyć metod, takich jak$a->getActiveUsers()
. OK, mogę użyć$a->users->...
, ale zwracam kolekcję Eloquent bez obiektu stdClass i ponownie jestem powiązany z Eloquent. Jakie jest na to rozwiązanie? Deklarowanie innej metody w repozytorium użytkowników, na przykład$user->getActiveUsersByAccount($a->id);
? Chciałbym usłyszeć, jak rozwiązujesz ten ...Kończę duży projekt przy użyciu Laravel 4 i musiałem odpowiedzieć na wszystkie pytania, które teraz zadajesz. Po przeczytaniu wszystkich dostępnych książek Laravel w Leanpub i mnóstwie google, wymyśliłem następującą strukturę.
Powiedzmy, że tworzę bazę danych filmów. Miałbym przynajmniej następujące klasy Eloquent Model:
Klasa repozytorium hermetyzowałaby każdą klasę modelu elokwentnego i byłaby odpowiedzialna za operacje CRUD w bazie danych. Klasy repozytorium mogą wyglądać następująco:
Każda klasa repozytorium rozszerzyłaby klasę BaseRepository, która implementuje następujący interfejs:
Klasa Service służy do sklejania ze sobą wielu repozytoriów i zawiera prawdziwą „logikę biznesową” aplikacji. Kontrolery komunikują się tylko z klasami usług w przypadku akcji tworzenia, aktualizowania i usuwania.
Więc kiedy chcę utworzyć nowy rekord filmu w bazie danych, moja klasa MovieController może mieć następujące metody:
Do Ciebie należy określenie, w jaki sposób POST przekazujesz dane swoim kontrolerom, ale powiedzmy, że dane zwrócone przez Input :: all () w metodzie postCreate () wyglądają mniej więcej tak:
Ponieważ MovieRepository nie powinno wiedzieć, jak tworzyć rekordy aktora, reżysera lub studia w bazie danych, użyjemy naszej klasy MovieService, która może wyglądać mniej więcej tak:
Pozostaje więc przyjemne, rozsądne oddzielenie obaw. Repozytoria znają tylko model elokwentny, który wstawiają i pobierają z bazy danych. Administratorzy nie dbają o repozytoria, po prostu przekazują zebrane od użytkownika dane i przekazują je do odpowiedniej usługi. Serwis nie dba o to, w jaki sposób otrzymane dane są zapisywane w bazie danych, po prostu przekazuje odpowiednie dane, które otrzymała od administratora do odpowiednich repozytoriów.
źródło
$studio->movies()->associate($movie);
).Lubię myśleć o tym w kategoriach tego, co robi mój kod i za co jest odpowiedzialny, a nie „dobrze czy źle”. Oto jak rozdzielam swoje obowiązki:
Mając to na uwadze, sensowne jest używanie repozytorium za każdym razem (niezależnie od tego, czy tworzysz interfejsy. Itd. To zupełnie inny temat). Podoba mi się to podejście, ponieważ oznacza to, że dokładnie wiem, gdzie iść, kiedy muszę wykonać określoną pracę.
Mam również tendencję do budowania podstawowego repozytorium, zwykle abstrakcyjnej klasy, która definiuje główne ustawienia domyślne - w zasadzie operacje CRUD, a następnie każde dziecko może po prostu rozszerzyć i dodać metody w razie potrzeby lub przeciążać wartości domyślne. Wstrzyknięcie modelu również pomaga temu wzorowi być dość solidnym.
źródło
Pomyśl o repozytoriach jako o spójnej szafce na dane (nie tylko o ORMach). Chodzi o to, że chcesz pobierać dane w spójnym, prostym w użyciu interfejsie API.
Jeśli okaże się, że po prostu robisz Model :: all (), Model :: find (), Model :: create (), prawdopodobnie nie odniesiesz większych korzyści z wyodrębnienia repozytorium. Z drugiej strony, jeśli chcesz wprowadzić nieco więcej logiki biznesowej do swoich zapytań lub działań, możesz utworzyć repozytorium, aby ułatwić korzystanie z interfejsu API do obsługi danych.
Myślę, że pytałeś, czy repozytorium byłoby najlepszym sposobem radzenia sobie z niektórymi bardziej szczegółowymi składniami wymaganymi do połączenia powiązanych modeli. W zależności od sytuacji mogę zrobić kilka rzeczy:
Wieszając nowy model podrzędny z modelu nadrzędnego (jeden-jeden lub jeden-wiele), dodałbym metodę do repozytorium podrzędnego coś podobnego,
createWithParent($attributes, $parentModelInstance)
a to po prostu dodałoby$parentModelInstance->id
doparent_id
pola atrybutów i wywołał create.Dołączając relację wiele-wiele, faktycznie tworzę funkcje w modelach, aby móc uruchomić $ instance-> attachChild ($ childInstance). Zwróć uwagę, że wymaga to istniejących elementów po obu stronach.
Tworząc powiązane modele w jednym przebiegu, tworzę coś, co nazywam Gateway (może to być trochę odbiegające od definicji Fowlera). Sposób, w jaki mogę wywołać $ gateway-> createParentAndChild ($ parentAttributes, $ childAttributes) zamiast zbioru logiki, która może się zmienić lub która skomplikowałaby logikę, którą mam w kontrolerze lub poleceniu.
źródło