在我的ORM代码中,我有一个实体,它的字段定义如下:
//part of entity class Item:
/** @Column(name="product_id", type="integer") */
private $productId;
然后我执行了这个代码:
//3 lines ~straight out of Doctrine configuration to get EntityManager
include 'config/doctrine-config.php';
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$em = EntityManager::create($dbParams, $config);
//my own code to retrieve an entity instance:
$instance = $em->find(Item::class, 2);
print_r($instance);
这是我得到的输出(跳过其他一些类似的属性):
ApplicationEntityItem Object
(
[id:ApplicationEntityItem:private] => 2
[description:ApplicationEntityItem:private] => Product Kit
[productId:ApplicationEntityItem:private] => -1
)
请注意,上面有6(六)行来自print_r()
函数。
一切都很好,直到
接下来,我在Item
实体类上将$productId
列更改为ManyToOne
关系,如下所示:
/**
* @ManyToOne(targetEntity="Product", inversedBy="id")
* @JoinColumn(name="product_id", referencedColumnName="id")
*/
private $productId;
我运行了相同的代码。
2392600行的宇宙出现了,什么
2000000九万二千六百行print_r
输出行。
查看打印输出,我发现DoctrineProxies__CG__ApplicationEntityProduct
对象包含print_r
打印的2,392,564
行
问题:
这个物体到底是什么?为什么它这么大,打印出来时会占用近300Mb的磁盘空间?
我不禁想知道,这种复杂性是否会导致日常代码出现性能问题。例如,我并没有在日常代码中打印$instance
变量的内容,但我肯定会从方法调用中返回巨大的内容。这是否意味着它是从上面的$em->find(Item::class, 2);
调用传递的300Mb变量?
(非常)部分上市
ApplicationEntityItem Object
(
[id:ApplicationEntityItem:private] => 2
[description:ApplicationEntityItem:private] => Product Kit
[ProductId:ApplicationEntityItem:private] => DoctrineProxies__CG__ApplicationEntityProduct Object
(
[__initializer__] => Closure Object
(
[static] => Array
(
[entityPersister] => DoctrineORMPersistersEntityBasicEntityPersister Object
(
[class:protected] => DoctrineORMMappingClassMetadata Object
(
[name] => ApplicationEntityProduct
[namespace] => ApplicationEntity
[rootEntityName] => ApplicationEntityProduct
[inheritanceType] => 1
[generatorType] => 5
[fieldMappings] => Array
(
[id] => Array
(
[fieldName] => id
[type] => integer
[scale] => 0
[length] =>
[unique] =>
[nullable] =>
[precision] => 0
[columnName] => id
[id] => 1
)
[fieldNames] => Array
(
[id] => id
[description] => description
)
[columnNames] => Array
(
[id] => id
[description] => description
)
[idGenerator] => DoctrineORMIdAssignedGenerator Object
[reflClass] => ReflectionClass Object
(
[name] => ApplicationEntityProduct
)
[namingStrategy:protected] => DoctrineORMMappingDefaultNamingStrategy Object
[instantiator:DoctrineORMMappingClassMetadataInfo:private] => DoctrineInstantiatorInstantiator Object
)
[conn:protected] => DoctrineDBALConnection Object
(
[_conn:protected] => DoctrineDBALDriverPDOConnection Object
(
)
[_config:protected] => DoctrineORMConfiguration Object
(
[_attributes:protected] => Array
(
[metadataCacheImpl] => DoctrineCommonCacheArrayCache Object
(
[data:DoctrineCommonCacheArrayCache:private] => Array
(
[dc2_b1e855bc8c5c80316087e39e6c34bc26_[ApplicationEntityItem$CLASSMETADATA][1]] => Array
(
[0] => DoctrineORMMappingClassMetadata Object
(
[name] => ApplicationEntityItem
[namespace] => ApplicationEntity
[rootEntityName] => ApplicationEntityItem
[customGeneratorDefinition] =>
[customRepositoryClassName] =>
[isMappedSuperclass] =>
[isEmbeddedClass] =>
[parentClasses] => Array
[BAZILLION LINES redacted for brevity]
如果没有XDebug或类似工具(限制转储对象的大小),就无法转储代理对象。
问题非常非常简单:
Proxy->引用EntityManager->引用UnitOfWork->包含Proxy
这显然会导致递归数据结构转储,而当您试图在没有合理限制的情况下转储它时,这反过来又会导致混乱。
DoctrineProxies__CG__ApplicationEntityProduct
是代理类。。。这意味着条令实际上不会从数据库中获取实体(为了性能),除非需要(即调用$product->getName()
,这些代理类彼此处于递归循环中,并且如您所见非常大……那里的大多数信息除非您深入研究,否则您并不真正需要……您永远不应该在新的symfony 2.7+中使用print_r
……我认为在调试模式下有一个名为dump()
的函数……如果您使用它来打印实体,它具有循环保护,并且它只显示参考参考号。。。你也可以使用DoctrineCommonUtilDebug::dump()
,它也会打印出比2^234234234行更小的列表。。。