W jaki sposób ORM udaje się zrealizować funkcje, takie jak powiązane akcesoria i jak duże są zazwyczaj działania?
Nikt chyba nie odpowiedział na to pytanie. Mogę szybko opisać, w jaki sposób Doctrine robi to w PHP.
W Doctrine, żadne z pól widocznych w modelu obiektowym nie jest faktycznie zdefiniowane dla tej klasy. W twoim przykładzie, $ car-> owners, nie ma faktycznego pola o nazwie "owner" zdefiniowanego w klasie $ car.
Zamiast tego ORM używa magicznych metod, takich jak __get and __set. Więc jeśli użyjesz wyrażenia takiego jak $ car-> color, wewnętrznie wywołaj PHP Doctrine_Record #__ get ('color').
W tym momencie ORM może to zaspokoić w razie potrzeby. Istnieje wiele możliwych projektów tutaj. Może przechowywać te wartości w tablicy o nazwie $ _values, na przykład, a następnie zwrócić $ this -> _ values ['color']. Doctrine w szczególności śledzi nie tylko wartości każdego rekordu, ale także jego status względem trwałości w bazie danych.
Jednym z przykładów tego, co nie jest intuicyjne, są relacje Doctrine. Kiedy dostajesz odniesienie do samochodu $, ma on związek z tabelą Osoby, która nazywa się "właściciele". Tak więc dane dla $ car-> owners są w rzeczywistości przechowywane w osobnej tabeli z danych dla samego samochodu $. ORM ma dwie możliwości:
- Za każdym razem, gdy ładujesz $ użytkownika, ORM automatycznie dołącza do wszystkich powiązanych tabel i zapełnia informacje w obiekcie. Teraz, kiedy robisz $ car-> owners, dane już tam są. Ta metoda jest jednak powolna, ponieważ obiekty mogą mieć wiele relacji, a te relacje mogą same mieć relacje. Więc dodajesz wiele połączeń i niekoniecznie korzystasz z tych informacji.
- Za każdym razem, gdy ładujesz $ user, ORM zauważa, które pola są załadowane z tabeli User i zapełnia je, ale żadne pola załadowane z powiązanych tabel nie są załadowane. Zamiast tego niektóre metadane są dołączane do tych pól, aby oznaczyć je jako "nie załadowane, ale dostępne". Teraz, gdy napiszesz wyrażenie $ car-> właściciele, ORM widzi, że relacja "właściciele" nie została załadowana, i wydaje osobne zapytanie, aby uzyskać te informacje, dodać je do obiektu, a następnie zwrócić te dane. Wszystko to dzieje się w sposób przejrzysty, bez potrzeby uświadamiania sobie tego.
Oczywiście Doctrine używa numeru 2, ponieważ numer 1 staje się niewygodny w przypadku prawdziwej witryny produkcyjnej o umiarkowanej złożoności. Ale ma również skutki uboczne. Jeśli używasz kilku relacji w $ car, Doctrine załaduje każdy z nich osobno, gdy będziesz mieć do niego dostęp. Tak więc kończysz z 5-6 zapytaniami, gdy tylko może być wymagana tylko jedna.
Doctrine pozwala zoptymalizować tę sytuację za pomocą Doctrine Query Language. Poinformujesz DQL, że chcesz załadować obiekt samochodu, ale także dołączyć do jego właścicieli, producenta, tytułów, zastawów itp. I załaduje wszystkie te dane do obiektów.
Whew! Długa odpowiedź. Zasadniczo jednak dostałeś się w sedno "Jaki jest cel ORM?" i "Dlaczego powinniśmy używać jednego?" ORM pozwala nam nadal myśleć w trybie obiektowym w większości przypadków, ale abstrakcja nie jest doskonała, a przecieki w abstrakcji mają tendencję do wychodzenia jako kary za wydajność.
Nie wolno antropomorfizować komputerów. Oni tego nie lubią. – finnw