Niedawno zacząłem czytać o wstrzyknięciu zależności i zmusiło mnie to do przemyślenia niektórych z moich projektów.PHP Leniwe obiekty ładujące i wtrysk zależności
Problem jaki mam jest taki: Załóżmy, że mam dwie klasy: samochód i pasażer; Dla tych dwóch klas Mam kilka mappers danych do pracy z bazą danych: CarDataMapper i PassengerDataMapper
Chcę być w stanie zrobić coś takiego w kodzie:
$car = CarDataMapper->getCarById(23); // returns the car object
foreach($car->getPassengers() as $passenger){ // returns all passengers of that car
$passenger->doSomething();
}
Przed Wiedziałem nic o DI, Chciałbym zbudować moje zajęcia tak:
class Car {
private $_id;
private $_passengers = null;
public function getPassengers(){
if($this->_passengers === null){
$passengerDataMapper = new PassengerDataMapper;
$passengers = $passengerDataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
Chciałbym również mieć podobny kod w metodzie przewozu pasażerów> getCar(), aby sprowadzić samochód pasażer jest w
.Teraz rozumiem, że to tworzy zależności (dobrze, ja też to rozumiałem wcześniej, ale nie wiedziałem, że to jest "złe") między pojazdem a obiektami pasażera i obiektami odwzorowującymi dane.
Starając się wymyślić rozwiązanie tego dwie opcje przyszło mi do głowy, ale ja nie lubię żadnego z nich:
1: Robi coś takiego:
$car = $carDataMapper->getCarById(23);
$passengers = $passengerDataMapper->getPassengersByCarId($car->getId());
$car->setPassengers($passengers);
foreach($car->getPassengers() as $passenger){
$passenger->doSomething();
}
ale co jeśli pasażerowie mają przedmioty, które muszą wstrzyknąć, a co jeśli gniazdowanie przejdzie na dziesięć lub dwadzieścia poziomów ... Skończyłbym tworzyć niemal każdy obiekt na początku mojej aplikacji, co z kolei wywoływałoby zapytanie do całej bazy danych podczas procesu. Jeśli muszę wysłać pasażera do innego obiektu, który musi coś zrobić z przedmiotami, które zatrzymuje pasażer, nie chcę natychmiast tworzyć tych obiektów.
2: Wstrzyknięcie mappers danych do obiektów samochodów i pasażerów i mających coś takiego:
class Car {
private $_id;
private $_passengers = null;
private $_dataMapper = null;
public function __construct($dataMapper){
$this->setDataMapper($dataMapper);
}
public function getPassengers(){
if($this->_passengers === null && $this->_dataMapper instanceof PassengerDataMapper){
$passengers = $this->_dataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
I dont like to lepiej, bo to nie jest jak samochód jest naprawdę nieświadomi odwzorowującego danych, i bez modułu odwzorowującego dane, samochód mógłby zachowywać się nieprzewidywalnie (nie powracający pasażerowie, gdy faktycznie je ma)
Moje pierwsze pytanie brzmi: Podejmuję tutaj całkowicie niewłaściwe podejście, ponieważ im bardziej na to patrzę , tym bardziej wygląda na to, że buduję ORM zamiast warstwy biznesowej?
Drugie pytanie brzmi: czy istnieje sposób oddzielenia obiektów i maperów danych w sposób, który umożliwiłby mi użycie obiektów opisanych w pierwszym bloku kodu?
Trzecie pytanie: Widziałem kilka odpowiedzi dla innych języków (niektóre wersje C, jak sądzę) rozwiązaniu tego problemu z czymś takim opisane tutaj: What is the proper way to inject a data access dependency for lazy loading? Ponieważ nie miałem czasu, aby bawić się z innymi Języki, to nie ma dla mnie sensu, więc byłbym wdzięczny, gdyby ktoś wyjaśnił przykłady w odnośniku w PHP-ish.
Przyjrzałem się także niektórym strukturom DI i przeczytałem o kontenerach DI i Inwersji kontroli, ale z tego, co zrozumiałem, są one używane do definiowania i wstrzykiwania zależności dla "nie-dynamicznych" klas, gdzie na przykład samochód Zależy od silnika, ale nie wymaga dynamicznego ładowania silnika z bazy danych, po prostu byłby instancjonowany i wstrzykiwany do samochodu.
Przepraszamy za długi post i dziękujemy z góry.
Być może zechcesz wymeldować się [PoEAA] (http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/ref=sr_1_1?ie=UTF8&qid=1350785602&sr=8-1&keywords= schematy + + enterprise + application + architecture) Mimo, że nie pomoże to w ogóle z [DI] (http://martinfowler.com/articles/injection.html) (to poprzedza powszechność) zdasz sobie sprawę, że nawet z Warstw biznesowych potrzebujesz ORM, która znajduje się pod nim. Zaleca się [Data Mapper] (http://martinfowler.com/eaaCatalog/dataMapper.html). +1 za pytanie, na które szukałem odpowiedzi. – xenoterracide
Dzięki za cynk.Ostatnio używam Doctrine2 w większości moich projektów, która jest ORM Data Mapper i okazuje się być całkiem łatwa w użyciu. – Pinetree