Obtenir entityManager à l'intérieur d'une entité
je voudrais utiliser, quelque chose comme:
$em = $this->getEntityManager();
à l'Intérieur d'une Entité.
je comprends que je devrais faire ce que d'un service mais pour certains tests, je veux accéder à partir d'une Entité.
Est-il possible de réaliser cela?
j'ai essayé:
$em = $this->getEntityManager();
$profile_avatar = $em->getRepository('bundle:Perfils')->findOneByUser($this-getId());
Mais n'est-ce pas de travail.
Fatal error: appel à une méthode non définie ProxieswebBundleEntityUserProxy:: getEntityManager() dans / opt/lampp/htdocs/web/src/Pct/bundle/Entity / User.php sur la ligne de 449
pourquoi j'essaie de le faire de cette façon?
j'ai 3 types d'utilisateurs: Facebook, Twitter et les utilisateurs de MyOwnWebsite. Chacun d'eux a un avatar différent qui lie le profil facebook, twitter ou autre, si son utilisateur myownwebsite, je récupère l'avatar à partir d'une URL dans une base de données. Pour l'instant, je ne veux pas créer un service, parce que je suis juste essayer de le faire fonctionner, de le tester, pas de créer un déploiement final. C'est pourquoi j'essaie d'appeler le directeur D'entité d'une entité. Je ne veux pas, pour l'instant, modifier des fichiers de configuration, juste cette entité.
5 réponses
comme l'a souligné (encore) un commentateur, un gestionnaire d'entité à l'intérieur d'une entité est une odeur de code. Pour la situation spécifique de L'OP où il souhaitait acquérir le gestionnaire d'entité, avec le moins d'ennui, une simple injection de setter serait la plus fiable (contrairement à mon exemple original Injection via constructeur).
pour quiconque se retrouvant ici à la recherche d'une solution supérieure au même problème, il y a 2 façons d'y arriver ceci:
mise en oeuvre de la
ObjectManagerAware
interface comme suggéré par https://stackoverflow.com/a/24766285/1349295use 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; } }
Ou, à l'aide de la
@postLoad
/@postPersist
callbacks du cycle de vie et acquisition du gestionnaire d'entity en utilisant leLifecycleEventArgs
argument comme suggéré par https://stackoverflow.com/a/23793897/1349295use 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()); } }
réponse originale
en utilisant un EntityManager
à partir de l'intérieur d'un Entity
est une très mauvaise pratique. Faire défait le but de découplage de la requête et à la persistance des opérations de l'entité elle-même.
Mais, si vous avez vraiment, vraiment, vraiment besoin d'un gestionnaire d'entité dans une entité et ne peut pas faire autrement, puis à l'injecter dans l'entité.
class Entity
{
private $em;
public function __contruct($em)
{
$this->em = $em;
}
}
puis invoquer comme new Entity($em)
.
Meilleur moyen est d'utiliser le Cycle de Vie: @ORM\HasLifecycleCallbacks
Et vous pouvez utiliser l'Événement que vous souhaitez obtenir de résultat:
@postLoad
@postPersist
...
appeler le Gestionnaire D'entité de l'intérieur d'une entité est une mauvaise pratique! Vous devez garder vos entités aussi simples que possible.
dans quel but devez-vous appeler le Gestionnaire D'entité d'une entité?
ce que je pense que vous devriez faire est, au lieu d'utiliser le Gestionnaire D'Entity à l'intérieur de votre entity, de créer un dépôt personnalisé pour votre entity.
dans votre fichier ORM entity, ajoutez une entrée comme suit (ou dans vos annotations de classe entity si vous n'utilisez pas 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
maintenant, créez une nouvelle classe PHP qui a l'espace de noms ci-dessus:
//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;
}
}
Enfin, dans votre Contrôleur:
// Your controller
<?php
namespace <class namespace>;
...
use App\Bundle\CustomRepos\ProfilsRepository;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
...
class YourClassNameController extends Controller
{
public function yourAction()
{
$userId = <get the user ID>;
// 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);
...
}
}
vous devez configurer les services.yml:
services:
your_service_name:
class: AppBundle\Controller\ServiceController
arguments: [ @doctrine.orm.entity_manager ]
vous devez aussi définir le Controller avec le constructeur suivant:
public function __construct(\Doctrine\ORM\EntityManager $em)
{
$this->em = $em;
}
et utiliser $this->em
dans le controller
(par exemple,$connection = $this->em->getConnection();
)