AKTUALIZACJA
Ta odpowiedź zawiera błędne informacje o różnicach między obiektami zastępczymi a obiektami częściowymi. Zobacz odpowiedź @ Kontrollfreak, aby uzyskać więcej informacji: https://stackoverflow.com/a/17787070/252591
Obiekty proxy są używane zawsze, gdy zapytanie nie zwraca wszystkich danych wymaganych do utworzenia jednostki. Wyobraź sobie następujący scenariusz:
@Entity
class User {
@Column protected $id;
@Column protected $username;
@Column protected $firstname;
@Column protected $lastname;
// bunch of setters/getters here
}
DQL query:
SELECT u.id, u.username FROM Entity\User u WHERE u.id = :id
Jak widać to zapytanie nie zwraca firstname
i nie ma lastname
właściwości, dlatego nie można utworzyć User
obiektu. Utworzenie niekompletnej jednostki może prowadzić do nieoczekiwanych błędów.
Dlatego Doctrine stworzy UserProxy
obiekt obsługujący leniwe ładowanie. Kiedy spróbujesz uzyskać dostęp do firstname
właściwości (która nie jest załadowana), najpierw załaduje tę wartość z bazy danych.
Mam na myśli, dlaczego powinienem używać proxy?
Zawsze powinieneś pisać swój kod tak, jakbyś w ogóle nie używał obiektów proxy. Można je traktować jako wewnętrzne obiekty używane przez Doctrine.
Dlaczego leniwe ładowanie nie może zostać zaimplementowane w samej jednostce Entitiy?
Technicznie może to być, ale spójrz na klasę jakiegoś losowego obiektu proxy. Jest pełen brudnego kodu, ugh. Fajnie jest mieć czysty kod w swoich encjach.
Czy możesz podać mi przykład użycia?
Wyświetlasz listę ostatnich 25 artykułów i chcesz wyświetlić szczegóły pierwszego z nich. Każdy z nich zawiera dużą ilość tekstu, więc pobranie wszystkich tych danych byłoby stratą pamięci. Dlatego nie pobierasz niepotrzebnych danych.
SELECT a.title, a.createdAt
FROM Entity\Article a
ORDER BY a.createdAt DESC
LIMIT 25
$isFirst = true;
foreach ($articles as $article) {
echo $article->getTitle();
echo $article->getCreatedAt();
if ($isFirst) {
echo $article->getContent(); // Article::content is not loaded so it is transparently loaded
// for this single article.
$isFirst = false;
}
}
Proxy
Proxy Doctrine to po prostu opakowanie, które rozszerza klasę jednostki, aby zapewnić jej Lazy Loading.
Domyślnie, gdy poprosisz Entity Manager o jednostkę, która jest skojarzona z inną jednostką, skojarzona jednostka nie zostanie załadowana z bazy danych, ale zostanie opakowana w obiekt proxy. Gdy aplikacja zażąda następnie właściwości lub wywoła metodę tej jednostki proxy, Doctrine załaduje jednostkę z bazy danych (z wyjątkiem sytuacji, gdy zażądasz identyfikatora, który jest zawsze znany proxy).
Dzieje się to w pełni przezroczyste dla aplikacji ze względu na fakt, że serwer proxy rozszerza klasę jednostki.
Doctrine domyślnie nawadnia asocjacje jako serwery proxy z leniwym ładowaniem, jeśli
JOIN
ich nie uwzględnisz w zapytaniu lub ustawisz tryb pobierania naEAGER
.Teraz muszę to dodać, ponieważ nie mam wystarczającej reputacji, aby komentować wszędzie:
Niestety odpowiedź Crozina zawiera dezinformację.
Jeśli wykonujesz zapytanie DQL, takie jak
nie otrzymasz (zastępowanego) obiektu encji, ale tablicę asocjacyjną. Dlatego nie można leniwie ładować żadnych dodatkowych właściwości.
Mając to na uwadze, dochodzi się do wniosku, że przykład użycia również nie zadziała. Aby uzyskać dostęp
$article
jako obiekt, należałoby zmienić DQL na coś takiego :Właściwość zwracana przez
getContent()
musiałaby być asocjacją, aby nie ładować właściwości treści wszystkich 25 jednostek.Częściowe obiekty
Jeśli chcesz częściowo załadować właściwości encji, które nie są skojarzeniami, musisz wyraźnie powiedzieć tej Doktrynie:
Daje to częściowo załadowany obiekt encji.
Ale uważaj, że częściowe obiekty nie są proxy! Leniwe ładowanie ich nie dotyczy. Dlatego używanie częściowych przedmiotów jest generalnie niebezpieczne i należy go unikać. Czytaj więcej: Częściowe obiekty - dokumentacja Doctrine 2 ORM 2
źródło