ATUALIZAR
Esta resposta contém informações incorretas sobre as diferenças entre objetos proxy e objetos parciais. Veja a resposta de @Kontrollfreak para mais detalhes: https://stackoverflow.com/a/17787070/252591
Objetos proxy são usados sempre que sua consulta não retorna todos os dados necessários para criar uma entidade. Imagine o seguinte cenário:
@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
Como você pode ver, esta consulta não retorna firstname
e lastname
propriedades, portanto, você não pode criar User
objeto. A criação de uma entidade incompleta pode levar a erros inesperados.
É por isso que o Doctrine criará UserProxy
objetos que suportam o carregamento lento. Quando você tentar acessarfirstname
propriedade (que não está carregada), primeiro carregará esse valor do banco de dados.
Quer dizer, por que devo usar um proxy?
Você deve sempre escrever seu código como se não usasse objetos proxy. Eles podem ser tratados como objetos internos usados pelo Doctrine.
Por que o carregamento lento não pode ser implementado na própria entidade?
Tecnicamente, poderia ser, mas dê uma olhada na classe de algum objeto proxy aleatório. Está cheio de códigos sujos, ugh. É bom ter um código limpo em suas entidades.
Você pode me fornecer um caso de uso?
Você está exibindo uma lista dos 25 artigos mais recentes e deseja exibir os detalhes do primeiro. Cada um deles contém uma grande quantidade de texto, portanto, buscar todos esses dados seria um desperdício de memória. É por isso que você não busca dados desnecessários.
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;
}
}
Proxies
Um proxy Doctrine é apenas um wrapper que estende uma classe de entidade para fornecer Lazy Loading para ela.
Por padrão, quando você pede ao Entity Manager por uma entidade que está associada a outra entidade, a entidade associada não será carregada do banco de dados, mas empacotada em um objeto proxy. Quando seu aplicativo então solicita uma propriedade ou chama um método desta entidade com proxy, o Doctrine irá carregar a entidade do banco de dados (exceto quando você solicitar o ID, que é sempre conhecido pelo proxy).
Isso acontece de forma totalmente transparente para o seu aplicativo devido ao fato de que o proxy estende sua classe de entidade.
O Doctrine irá, por padrão, hidratar as associações como proxies de carregamento lento se você não
JOIN
os fizer em sua consulta ou definir o modo de busca paraEAGER
.Agora devo acrescentar isso porque não tenho reputação suficiente para comentar em todos os lugares:
Infelizmente, a resposta de Crozin contém informações incorretas.
Se você executar uma consulta DQL como
você não obterá um objeto de entidade (com proxy), mas uma matriz associativa. Portanto, não é possível carregar lentamente nenhuma propriedade adicional.
Com isso em mente, chega-se à conclusão de que o exemplo de caso de uso também não funcionará. O DQL teria que ser alterado para algo assim para acessar
$article
como objeto:E a propriedade retornada por
getContent()
teria que ser uma associação para não carregar as propriedades de conteúdo de todos 25 entidades.Objetos Parciais
Se você deseja carregar parcialmente as propriedades da entidade que não são associações, você deve informar esta Doutrina explicitamente:
Isso fornece um objeto de entidade parcialmente carregado.
Mas cuidado, pois objetos parciais não são proxies! O Lazy Loading não se aplica a eles. Portanto, usar objetos parciais é geralmente perigoso e deve ser evitado. Leia mais: Objetos Parciais - Doctrine 2 ORM 2 documentação
fonte