原则 2 中的代理人是什么?
我刚刚读完所有 Doctrine 2 文档,我开始了自己的沙箱,我理解了大部分原理,但仍然有一个问题,我在文档中找不到任何完整的解释。
- 什么是 Proxy 类?
- 我什么时候应该在实体上使用它们?
据我了解,代理类添加了一个层,让您可以向实体添加一些其他功能,但为什么要使用代理而不是在实体类中实现方法本身呢?
I just finished reading all the Doctrine 2 documentation, I started my own sandbox, I understood most of the principes, but there is still a question and I couldn't find any complete explanation in the doc.
- What are
Proxy
classes? - When should I use them over entities?
As far as I understand, proxy classes add a layer to let you add some other features to your entities, but why use a proxy instead of implementing the methods themselves in the entity class?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
每当使用代理对象时您的查询不会返回创建实体所需的所有数据。想象一下以下场景:
如您所见,此查询不会返回
firstname
和lastname
属性,因此您无法创建User
对象。创建不完整的实体可能会导致意外错误。这就是为什么 Doctrine 将创建支持延迟加载的
UserProxy
对象。当您尝试访问firstname
属性(未加载)时,它将首先从数据库加载该值。您应该始终像根本不使用代理对象一样编写代码。它们可以被视为 Doctrine 使用的内部对象。
从技术上讲,它可能是,但看看一些随机代理对象的类。它充满了肮脏的代码,呃。在您的实体中拥有干净的代码是件好事。
您正在显示最新 25 篇文章的列表,并且想要显示第一篇文章的详细信息。每个数据都包含大量文本,因此获取所有数据会浪费内存。这就是为什么你不获取不必要的数据。
Proxy objects are used whenever your query doesn't return all data required to create an entity. Imagine following scenario:
As you can see this query doesn't return
firstname
andlastname
properties, therefore you cannot createUser
object. Creation of incomplete entity could lead to unexpected errors.That's why Doctrine will create
UserProxy
object that supports lazy loading. When you'll try to accessfirstname
property (which is not loaded) it will first load that value from database.You should always write your code as if you didn't use proxy objects at all. They can be treated as internal objects used by Doctrine.
Technically it could be but take a look at some random proxy object's class. It's full of dirty code, ugh. It's nice to have a clean code in your entities.
You're displaying a list of latest 25 articles and you want to display a details of the first one. Each of them contain a large amount of text, so fetching all that data would be a waste of memory. That's why you don't fetch unnecessary data.
代理
Doctrine 代理只是一个扩展实体类以为其提供延迟加载的包装器。
默认情况下,当您向实体管理器请求与另一个实体关联的实体时,关联的实体不会从数据库加载,而是包装到代理对象中。然后,当您的应用程序请求该代理实体的属性或调用该代理实体的方法时,Doctrine 将从数据库加载该实体(除非您请求 ID,代理始终知道该 ID)。
由于代理扩展了您的实体类,因此这种情况对您的应用程序来说是完全透明的。
如果您没有在查询中
JOIN
或将获取模式设置为EAGER
,Doctrine默认会将关联关联作为延迟加载代理。现在我必须添加这一点,因为我没有足够的声誉来到处发表评论:
不幸的是,克罗津的答案包含错误信息。
如果您执行 DQL 查询,
您将不会获得(代理的)实体对象,而是获得关联数组。因此不可能延迟加载任何附加属性。
考虑到这一点,我们得出的结论是用例示例也不起作用。
必须将 DQL 更改为类似以下内容才能将
$article
作为对象进行访问:并且
getContent()
返回的属性必须是关联才能访问不加载所有 25 个实体的内容属性。部分对象
如果你想部分加载不是关联的实体属性,你必须明确地告诉这个 Doctrine:
这给你一个部分加载的实体对象。
但请注意,部分对象不是代理!延迟加载不适用于它们。因此,使用部分对象通常是危险的,应该避免。了解更多:部分对象 — Doctrine 2 ORM 2 文档
Proxies
A Doctrine proxy is just a wrapper that extends an entity class to provide Lazy Loading for it.
By default, when you ask the Entity Manager for an entity that is associated with another entity, the associated entity won't be loaded from the database, but wrapped into a proxy object. When your application then requests a property or calls a method of this proxied entity, Doctrine will load the entity from the database (except when you request the ID, which is always known to the proxy).
This happens fully transparent to your application due to the fact that the proxy extends your entity class.
Doctrine will by default hydrate associations as lazy load proxies if you don't
JOIN
them in your query or set the fetch mode toEAGER
.Now I must add this because I don't have enough reputation to comment everywhere:
Unfortunately, Crozin's answer contains misinformation.
If you execute a DQL query like
you won't get a (proxied) entity object, but an associative array. So it's not possible to lazy load any additional properties.
With this in mind, one comes to the conclusion that the use case example won't work either.
The DQL would have to be changed to something like this in order to access
$article
as object:And the property returned by
getContent()
would have to be an association in order not to load the content properties of all 25 entities.Partial Objects
If you want to partially load entity properties that are not associations, you have to tell this Doctrine explicitly:
This gives you a partially loaded entity object.
But beware that partial objects are not proxies! Lazy Loading doesn't apply to them. Therefore, using partial objects is generally dangerous and should be avoided. Read more: Partial Objects — Doctrine 2 ORM 2 documentation