В моем коде 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 в моем классе Item
Entity, например:
/**
* @ManyToOne(targetEntity="Product", inversedBy="id")
* @JoinColumn(name="product_id", referencedColumnName="id")
*/
private $productId;
Я запустил тот же код.
ВЫШЛА ВСЕЛЕННАЯ ИЗ 2 392 600 ЛИНИЙ, ЧТО?
Два миллиона триста девяносто две тысячи шестьсот строк строк вывода print_r
.
Глядя на распечатку, я вижу, что DoctrineProxies\__CG__\Application\Entity\Product
Объект содержит 2,392,564
строк, напечатанных print_r
Вопрос:
Что именно находится в этом объекте и почему он такой большой, что при распечатке занимает почти 300 МБ дискового пространства?
Я не могу не задаться вопросом, может ли такая сложность вызывать проблемы с производительностью в повседневном коде. Например, я не распечатываю содержимое переменной $instance
в своем повседневном коде, но я обязательно возвращаю громадность вызова метода. Означает ли это, что это 300-мегабайтная переменная, которая передается из вызова $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]
2 ответа
Вы не можете выгрузить прокси-объект без XDebug или аналогичных инструментов (которые ограничивают размер выгружаемого объекта).
Проблема действительно очень проста:
Прокси -> ссылки EntityManager -> ссылки UnitOfWork -> содержит прокси
Это, очевидно, приводит к рекурсивному дампу структуры данных, что, в свою очередь, приводит к беспорядку всякий раз, когда вы пытаетесь сбросить его без разумных ограничений.
DoctrineProxies\__CG__\Application\Entity\Product
является прокси-классом ... что означает, что доктрина фактически не извлекает объект из базы данных (для производительности), если он не нужен (т.е. вызов $product->getName()
, эти прокси-классы находятся в рекурсивном цикле друг с другом и ОЧЕНЬ большой, как вы видели ... большая часть информации там вам действительно не нужна, если вы не ныряете глубоко ... вам никогда не следует использовать print_r
... в новой версии Symfony 2.7+, я думаю, есть функция называется dump()
в режиме отладки ... если вы используете это для печати объекта, у него есть защита от петель, и он просто показывает ссылочные номера ... вы также можете использовать \Doctrine\Common\Util\Debug::dump()
, который также распечатает меньший список, чем 2 ^ 234234234 строк ...
Похожие вопросы
Новые вопросы
php
PHP — это открытый, мультипарадигмальный, динамически типизированный и интерпретируемый язык сценариев, изначально разработанный для веб-разработки на стороне сервера. Используйте этот тег для вопросов о программировании на языке PHP.