ОБНОВИТЬ
Этот ответ содержит неверную информацию о различиях между прокси-объектами и частичными объектами. Подробнее см. Ответ @ Kontrollfreak: https://stackoverflow.com/a/17787070/252591
Прокси-объекты используются всякий раз, когда ваш запрос не возвращает все данные, необходимые для создания объекта. Представьте себе следующий сценарий:
@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
Как видите, этот запрос не возвращает firstname
и lastname
свойства, поэтому вы не можете создать User
объект. Создание неполного объекта может привести к непредвиденным ошибкам.
Вот почему Doctrine создаст UserProxy
объект, поддерживающий отложенную загрузку. Когда вы попытаетесь получить доступ к firstname
свойству (которое не загружено), оно сначала загрузит это значение из базы данных.
Я имею ввиду, почему я должен использовать прокси?
Вы всегда должны писать свой код так, как если бы вы вообще не использовали прокси-объекты. Их можно рассматривать как внутренние объекты, используемые Doctrine.
Почему ленивая загрузка не может быть реализована в самом Entitiy?
Технически это могло быть, но взгляните на какой-нибудь случайный класс прокси-объекта. Там полно грязного кода, тьфу. Приятно иметь чистый код в ваших сущностях.
Можете ли вы предоставить мне пример использования?
Вы отображаете список из 25 последних статей и хотите отобразить подробную информацию о первой. Каждый из них содержит большой объем текста, поэтому получение всех этих данных будет пустой тратой памяти. Вот почему вы не получаете ненужные данные.
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;
}
}
Доверенные
Прокси-сервер Doctrine - это просто оболочка, которая расширяет класс сущности, чтобы обеспечить для него отложенную загрузку.
По умолчанию, когда вы запрашиваете у Entity Manager сущность, которая связана с другой сущностью, связанная сущность не загружается из базы данных, а упаковывается в прокси-объект. Когда ваше приложение затем запрашивает свойство или вызывает метод этой прокси-сущности, Doctrine загружает сущность из базы данных (кроме случаев, когда вы запрашиваете идентификатор, который всегда известен прокси).
Это происходит полностью прозрачно для вашего приложения из-за того, что прокси расширяет ваш класс сущности.
Doctrine по умолчанию будет гидратировать ассоциации как прокси с отложенной загрузкой, если вы не укажете
JOIN
их в своем запросе или установите для режима выборки значениеEAGER
.Теперь я должен добавить это, потому что у меня недостаточно репутации, чтобы комментировать везде:
К сожалению, ответ Крозина содержит дезинформацию.
Если вы выполните запрос DQL, например
вы не получите объект сущности (прокси), а получите ассоциативный массив. Поэтому ленивая загрузка дополнительных свойств невозможна.
Имея это в виду, можно прийти к выводу, что пример варианта использования тоже не работает. Чтобы получить доступ
$article
как объект, необходимо изменить DQL на что-то вроде этого :И возвращаемое свойство
getContent()
должно быть ассоциацией, чтобы не загружать свойства содержимого всех 25 сущностей.Частичные объекты
Если вы хотите частично загрузить свойства сущности, которые не являются ассоциациями, вы должны явно указать этой Доктрине:
Это дает вам частично загруженный объект сущности.
Но помните, что частичные объекты не являются прокси! Ленивая загрузка к ним не применяется. Следовательно, использование частичных объектов обычно опасно, и этого следует избегать. Подробнее: Частичные объекты - документация Doctrine 2 ORM 2
источник