ACTUALIZAR
Esta respuesta contiene información incorrecta sobre las diferencias entre los objetos proxy y los objetos parciales. Consulte la respuesta de @ Kontrollfreak para obtener más detalles: https://stackoverflow.com/a/17787070/252591
Los objetos proxy se utilizan siempre que su consulta no devuelve todos los datos necesarios para crear una entidad. Imagina el siguiente escenario:
@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 se puede ver esta consulta no devuelve firstname
y lastname
propiedades, por lo tanto, no puede crear User
objeto. La creación de una entidad incompleta podría dar lugar a errores inesperados.
Es por eso que Doctrine creará un UserProxy
objeto que admita la carga diferida. Cuando intente acceder a la firstname
propiedad (que no está cargada), primero cargará ese valor de la base de datos.
Quiero decir, ¿por qué debería usar un proxy?
Siempre debe escribir su código como si no usara objetos proxy en absoluto. Pueden tratarse como objetos internos utilizados por Doctrine.
¿Por qué la carga diferida no se puede implementar en la propia Entidad?
Técnicamente podría serlo, pero eche un vistazo a la clase de algún objeto proxy aleatorio. Está lleno de código sucio, uf. Es bueno tener un código limpio en sus entidades.
¿Puede proporcionarme un caso de uso?
Está mostrando una lista de los últimos 25 artículos y desea mostrar los detalles del primero. Cada uno de ellos contiene una gran cantidad de texto, por lo que recuperar todos esos datos sería una pérdida de memoria. Por eso no obtiene datos innecesarios.
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
Un proxy de Doctrine es solo un contenedor que extiende una clase de entidad para proporcionarle Carga diferida.
De forma predeterminada, cuando le solicita al Administrador de entidades una entidad que está asociada con otra entidad, la entidad asociada no se cargará desde la base de datos, sino que se incluirá en un objeto proxy. Cuando su aplicación luego solicita una propiedad o llama a un método de esta entidad proxed, Doctrine cargará la entidad desde la base de datos (excepto cuando solicite la ID, que siempre es conocida por el proxy).
Esto sucede de forma totalmente transparente para su aplicación debido al hecho de que el proxy extiende su clase de entidad.
Doctrine hidratará de forma predeterminada las asociaciones como proxies de carga diferida si no las
JOIN
incluye en su consulta o establece el modo de recuperación enEAGER
.Ahora debo agregar esto porque no tengo suficiente reputación para comentar en todas partes:
Desafortunadamente, la respuesta de Crozin contiene información errónea.
Si ejecuta una consulta DQL como
no obtendrá un objeto de entidad (proxy), sino una matriz asociativa. Por lo tanto, no es posible cargar de forma diferida propiedades adicionales.
Con esto en mente, se llega a la conclusión de que el ejemplo de caso de uso tampoco funcionará. El DQL tendría que cambiarse a algo como esto para poder acceder
$article
como objeto:Y la propiedad devuelta por
getContent()
tendría que ser una asociación para no cargar las propiedades de contenido de las 25 entidades.Objetos parciales
Si desea cargar parcialmente propiedades de entidad que no son asociaciones, debe decirle a esta Doctrine explícitamente:
Esto le da un objeto de entidad parcialmente cargado.
¡Pero tenga en cuenta que los objetos parciales no son proxies! La carga diferida no se aplica a ellos. Por lo tanto, el uso de objetos parciales es generalmente peligroso y debe evitarse. Leer más: Objetos parciales - documentación de Doctrine 2 ORM 2
fuente