Obtener entityManager dentro de una entidad

Me gustaría usar, algo así como:

$em = $this->getEntityManager(); 

Dentro de una entidad.

Entiendo que debería hacer esto como un servicio, pero para algunas pruebas, quiero acceder a él desde una Entidad.

¿Es posible lograr eso?

He intentado:

 $em = $this->getEntityManager(); $profile_avatar = $em->getRepository('bundle:Perfils')->findOneByUser($this-getId()); 

Pero no está funcionando.

Error fatal : llamada al método indefinido Proxies \ webBundleEntityUserProxy :: getEntityManager () en /opt/lampp/htdocs/web/src/Pct/bundle/Entity/User.php en la línea 449

¿Por qué estoy tratando de hacerlo de esta manera?

Tengo 3 tipos de usuarios: usuarios de Facebook, Twitter y MyOwnWebsite. Cada uno de ellos tiene diferentes avatares que enlazan el perfil de Facebook, Twitter o cualquier otro, si es un usuario de mi sitio web, recupero el avatar de una URL en una base de datos. Por ahora, no quiero crear un servicio, porque solo estoy tratando de hacerlo funcionar, probarlo, no crear una implementación final. Entonces, esta es la razón por la que trato de llamar al administrador de Entidad desde una Entidad. No quiero, por ahora, modificar los archivos de configuración, solo esta entidad.

Como lo señala (nuevamente) un comentarista, un administrador de entidades dentro de una entidad es un olor codificado. Para la situación específica del OP donde deseaba adquirir el administrador de la entidad, con la menor molestia, una inyección de setter simple sería la más confiable (al contrario de mi ejemplo original de inyección a través del constructor).

Para cualquiera que termine buscando una solución superior para el mismo problema, hay dos formas de lograrlo:

  1. Implementar la interfaz ObjectManagerAware como lo sugiere https://stackoverflow.com/a/24766285/1349295

     use Doctrine\Common\Persistence\ObjectManagerAware; use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\Mapping\ClassMetadata; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Entity implements ObjectManagerAware { public function injectObjectManager( ObjectManager $objectManager, ClassMetadata $classMetadata ) { $this->em = $objectManager; } } 
  2. O bien, utilizando las devoluciones de llamada del ciclo de vida @postLoad / @postPersist y adquiriendo el administrador de entidades utilizando el argumento LifecycleEventArgs como lo sugiere https://stackoverflow.com/a/23793897/1349295

     use Doctrine\Common\Persistence\Event\LifecycleEventArgs; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\HasLifecycleCallbacks() */ class Entity { /** * @ORM\PostLoad * @ORM\PostPersist */ public function fetchEntityManager(LifecycleEventArgs $args) { $this->setEntityManager($args->getEntityManager()); } } 

Respuesta original

Usar un EntityManager desde dentro de una Entity es MUY MALA PRÁCTICA. Hacerlo derrota el propósito de desacoplar las operaciones de consulta y persistencia de la propia entidad.

Pero, si realmente, realmente, realmente necesita un administrador de entidades en una entidad y no puede hacerlo de otra manera, entonces inyéctelo en la entidad.

 class Entity { private $em; public function __contruct($em) { $this->em = $em; } } 

Luego invoque como new Entity($em) .

La mejor forma es usar Life Cycle: @ORM\HasLifecycleCallbacks

Y puede usar el evento apropiado como quiera obtener el resultado:

 @postLoad @postPersist ... 

¡Llamar al administrador de la entidad desde dentro de una entidad es una mala práctica! Debes mantener tus entidades lo más simples posible.

¿Para qué necesita llamar al Gerente de la Entidad desde una Entidad?

Lo que creo que debe hacer es, en lugar de usar el Administrador de Entidades dentro de su entidad, crear un repository personalizado para su entidad.

En el archivo ORM de su entidad, agregue una entrada de la siguiente manera (o en las anotaciones de su clase de entidad si no usa YML):

 App\Bundle\Profils: # Replace the above as appropiate type: entity table: (your table) .... repositoryClass: App\Bundle\CustomRepos\ProfilsRepository # Replace the above as appropiate. # I always put my custom repos in a common folder, # such as CustomRepos 

Ahora, crea una nueva clase PHP que tenga el espacio de nombres arriba:

 //Your ProfilsRepository.php < ?php namespace App\Bundle\CustomRepos; use Doctrine\ORM\EntityRepository; class ProfilsRepository extends EntityRepository { /** * Will return the user url avatar given the user ID * @param integer $userID The user id. @return string The avatar url */ public function getUserProfile($userId) { $em = $this->getEntityManager(); $qb = $em->createQueryBuilder(); $qb->select... (your logic to retrieve the profil object); $query = $qb->getQuery(); $result = $query->getResult(); return $result; } } 

Finalmente, en tu Controlador:

 // Your controller < ?php namespace ; ... use App\Bundle\CustomRepos\ProfilsRepository; use Symfony\Bundle\FrameworkBundle\Controller\Controller; ... class YourClassNameController extends Controller { public function yourAction() { $userId = ; // Pass the name of your entity manager to the // getManager function if you have more than one and // didn't define any default $em = $this->getDoctrine()->getManager(); $repo = $em->getRepository('Profils'); $avatar = $repo->getUserProfile($userId); ... } } 

Debes configurar services.yml con:

 services: your_service_name: class: AppBundle\Controller\ServiceController arguments: [ @doctrine.orm.entity_manager ] 

También debe configurar el controlador con el siguiente constructor:

 public function __construct(\Doctrine\ORM\EntityManager $em) { $this->em = $em; } 

y use $this->em en el controlador (por ejemplo $connection = $this->em->getConnection(); )