В моем ORM-коде у меня есть Entity с полем, оштрафованным так:
//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);
И это результат, который я получаю (пропускаю несколько других подобных свойств):
Application\Entity\Item Object ( [id:Application\Entity\Item:private] => 2 [description:Application\Entity\Item:private] => Product Kit [productId:Application\Entity\Item:private] => -1 )
Обратите внимание, что есть 6 (шесть) строк выше, которые вышли из функции print_r()
.
И все было хорошо, пока
Затем я изменил столбец $productId
на ManyToOne
Relationship на моем ManyToOne
Entity, например:
/** * @ManyToOne(targetEntity="Product", inversedBy="id") * @JoinColumn(name="product_id", referencedColumnName="id") */ private $productId;
Я запустил тот же код.
OUT CAME ВСЕЛЕННАЯ 2 392 600 ЛИНИЙ, ЧТО?
Две тысячи, триста девяносто две тысячи шестьсот строк линии print_r
.
глядя на распечатку, я вижу, что DoctrineProxies\__CG__\Application\Entity\Product
Object содержит 2 2,392,564
строки, напечатанных print_r
Вопрос:
Что именно в этом объекте и почему оно настолько велико, что при печати распечатано около 300 МБ дискового пространства?
Я не могу не задаться вопросом, может ли такая сложность вызвать проблемы с производительностью в ежедневном коде. Например, я не распечатываю содержимое переменной $instance
в моем ежедневном коде, но я, несомненно, возвращаю большую часть вызова метода. Означает ли это, что это переменная 300 Мбайт, которая передается из ie $em->find(Item::class, 2);
позвонить выше?
(Очень) Частичный список
Application\Entity\Item Object ( [id:Application\Entity\Item:private] => 2 [description:Application\Entity\Item:private] => Product Kit [ProductId:Application\Entity\Item:private] => DoctrineProxies\__CG__\Application\Entity\Product Object ( [__initializer__] => Closure Object ( [static] => Array ( [entityPersister] => Doctrine\ORM\Persisters\Entity\BasicEntityPersister Object ( [class:protected] => Doctrine\ORM\Mapping\ClassMetadata Object ( [name] => Application\Entity\Product [namespace] => Application\Entity [rootEntityName] => Application\Entity\Product [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] => Doctrine\ORM\Id\AssignedGenerator Object [reflClass] => ReflectionClass Object ( [name] => Application\Entity\Product ) [namingStrategy:protected] => Doctrine\ORM\Mapping\DefaultNamingStrategy Object [instantiator:Doctrine\ORM\Mapping\ClassMetadataInfo:private] => Doctrine\Instantiator\Instantiator Object ) [conn:protected] => Doctrine\DBAL\Connection Object ( [_conn:protected] => Doctrine\DBAL\Driver\PDOConnection Object ( ) [_config:protected] => Doctrine\ORM\Configuration Object ( [_attributes:protected] => Array ( [metadataCacheImpl] => Doctrine\Common\Cache\ArrayCache Object ( [data:Doctrine\Common\Cache\ArrayCache:private] => Array ( [dc2_b1e855bc8c5c80316087e39e6c34bc26_[Application\Entity\Item$CLASSMETADATA][1]] => Array ( [0] => Doctrine\ORM\Mapping\ClassMetadata Object ( [name] => Application\Entity\Item [namespace] => Application\Entity [rootEntityName] => Application\Entity\Item [customGeneratorDefinition] => [customRepositoryClassName] => [isMappedSuperclass] => [isEmbeddedClass] => [parentClasses] => Array [BAZILLION LINES redacted for brevity]
Вы не можете сбросить прокси-объект без XDebug или аналогичных инструментов (которые ограничивают размер сбрасываемого объекта).
Проблема действительно, очень простая:
Прокси -> ссылки EntityManager -> ссылки UnitOfWork -> содержит прокси
Это, очевидно, приводит к рекурсивному дампу структуры данных, что, в свою очередь, приводит к беспорядку в любое время, когда вы пытаетесь сбрасывать его без разумных ограничений.
DoctrineProxies\__CG__\Application\Entity\Product
– это прокси-класс … что означает, что доктрина фактически не извлекает сущность из базы данных (для производительности), если она не нужна (т. $product->getName()
этих прокси-серверов Классы находятся в рекурсивном цикле с eachother и очень велики, как вы видели … большая часть информации там вам действительно не нужна, если вы глубоко погружаетесь … вы никогда не должны использовать print_r
… в новом Symfony 2.7 + Я думаю, что есть функция, называемая dump()
в режиме отладки … если вы используете это для печати объекта, у которого есть защита цикла, и он просто показывает ссылочные номера … вы также можете использовать \Doctrine\Common\Util\Debug::dump()
который также распечатает меньший список, чем 2 ^ 234234234 строки …