How to check if a class is a Doctrine entity?
Courtesy Stof on the doctrine-dev mailing list:
return ! $em->getMetadataFactory()->isTransient($className);
I'll add that this method considers proxies (returned by the EntityManager as part of the lazy loading strategy) as transient; so if you're testing objects, don't blindly use get_class()
, be sure to test first:
$object instanceof \Doctrine\Common\Persistence\Proxy
Working implementation:
use Doctrine\Common\Persistence\Proxy;
use Doctrine\ORM\EntityManager;
function isEntity(EntityManager $em, string|object $class): bool
{
if (is_object($class)) {
$class = ($class instanceof Proxy)
? get_parent_class($class)
: get_class($class);
}
return ! $em->getMetadataFactory()->isTransient($class);
}
As an addition to Benjamin his answer...
If you know for sure that you are handling doctrine entities, but you are not sure whether you have a proxy or a instance of the real class you can easily retrieve the real class by using the Doctrine Common ClassUtils
:
use Doctrine\Common\Util\ClassUtils;
and then you can get the real class through the static getClass
method like this:
$proxyOrEntity;
$className = ClassUtils::getClass($proxyOrEntity);
So this means @Benjamin his isEntity
function can be written like this:
/**
* @param EntityManager $em
* @param string|object $class
*
* @return boolean
*/
function isEntity(EntityManager $em, $class)
{
if(is_object($class)){
$class = ClassUtils::getClass($class);
}
return ! $em->getMetadataFactory()->isTransient($class);
}
Which will give you true/false depending on whether the class is a doctrine entity or not.
One work around would be to test if you can generate a Repository. This is 'bullet proof' in that it will fail if the current schema and mapping does not know about the object class in question.
// Get the entity manager. I don't know how you do it
$em = new Doctrine\ORM\EntityManager();
try {
$repo = $em->getRepository('YourClassModel');
} catch (Doctrine\Common\Persistence\Mapping\MappingException $e) {
// NOPE! Not a mapped model
}