Doctrine uses proxy objects to represent related objects in order to facilitate lazy loading. This is a really cool feature, but its causing an issue with something I am trying
Edit: As mention by @flu this approach don't return the "true" object. However it can be useful in case if you need the data from the object. Then, you can just get the real object from ObjectManager by some of identity.
We can use __load() method from Proxy interface
$proxyObject->__load();
This is a little bit nasty workaround that issue :
// $proxyObject = ...
$em->detach($proxyObject);
$entityObject = $em->find(<ENTITY_CLASS>, $proxyObject->getId());
// now you have real entity and not the proxy (entityObject instead of proxyObject)
after that you can replace proxy reference if you need to have it inside other entities
Here is my solution:
All my entities have id
property and getId()
method
$em = $this->getDoctrine()->getManager();
// 1 -> get the proxy object class name
$proxy_class_name = get_class($proxyObject);
// 2 -> get the real object class name
$class_name = $em->getClassMetadata($proxy_class_name)->rootEntityName;
// 3 -> get the real object
$object = $em->find($class_name, $proxyObject->getId());
This solution don't work if id
property and getId()
method are in a Trait
class
I hope that it can help someone
The Symfony PropertyNormalizer gets around this issue using the ReflectionClass
getParent method. If you need to inspect the object, as for a normalizer, rather than just use the ->get
methods, you should be able to use a similar approach.
It appears the Proxy has a parent of the actual entity, which is why instanceof still works.
@mustaccio, @Heather Orr
I had this problem. Thanks for idea,
This is the code:
// $object is a Proxy class
$objectClass = get_class($object);
$reflectionClass = new \ReflectionClass($objectClass);
// Make sure we are not using a Proxy class
if ($obj instanceof Proxy) {
$reflClass = $reflClass->getParentClass();
}
Another way, if you just need to read annotations:
// $object is a Proxy class
$objectClass = get_class($object);
$classMetadata = $this->em->getClassMetadata($objectClass);
foreach ($classMetadata->getReflectionProperties() as $property) {
$annotation = $this->annotationReader->getPropertyAnnotation($property, YOUR_ANNOTATION::class)
}
Not absolutely related to original question, but I hope this will help some people...
If you first used $em->getReference
and then $em->find
, then the result will be a _proxy.
I recommend using:
createQueryBuilder ... ->getQuery()
->setHint (Query::HINT_FORCE_PARTIAL_LOAD, true)
->getOneOrNullResult();