Получить entityManager внутри объекта
Я бы хотел использовать, например:
$em = $this->getEntityManager();
Внутри объекта.
Я понимаю, что должен делать это как сервис, но для некоторых целей тестирования я хочу получить к нему доступ из Entity.
Можно ли это достичь?
Я пытался:
$em = $this->getEntityManager();
$profile_avatar = $em->getRepository('bundle:Perfils')->findOneByUser($this-getId());
Но не работает.
Неустранимая ошибка: вызов метода undefinedПрокси\webBundleEntityUserProxy:: getEntityManager() в /opt/lampp/htdocs/web/src/Pct/bundle/Entity/User.php в режиме онлайн <Б > 449
Почему я пытаюсь сделать это таким образом?
У меня 3 вида пользователей: Facebook, Twitter и MyOwnWebsite. У каждого из них есть аватар differents, который связывает профиль facebook, твиттер или иначе, если его пользователь myownwebsite, я получаю аватар из URL-адреса в базе данных. Пока я не хочу создавать службу, потому что я просто пытаюсь заставить ее работать, тестировать ее, а не создавать окончательное развертывание. Поэтому я пытаюсь вызвать менеджера Entity из Entity. Сейчас я не хочу изменять файлы конфигурации, только этот объект.
Ответы
Ответ 1
Как отмечалось (снова) комментатором, диспетчер сущности внутри объекта является запахом кода. Для конкретной ситуации с ОП, в которой он хотел приобрести менеджера сущности, с наименьшей проблемой, простая инсталляция сеттера была бы наиболее надежной (в отличие от моего первоначального примера, впрыскивающего через конструктор).
Для всех, кто в конечном итоге ищет превосходное решение для одной и той же проблемы, есть два способа добиться этого:
-
Реализация интерфейса ObjectManagerAware
, как предлагается fooobar.com/questions/173255/...
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;
}
}
-
Или, используя обратные вызовы жизненного цикла @postLoad
/@postPersist
и приобретая диспетчер объектов с помощью аргумента LifecycleEventArgs
, как предлагается fooobar.com/questions/406937/...
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());
}
}
Оригинальный ответ
Использование EntityManager
изнутри Entity
- ОЧЕНЬ ПЛОЩАДЬ. Это приводит к тому, что происходит развязка запросов и сохранение операций с самой сущностью.
Но, если вы действительно действительно нуждаетесь в менеджере сущностей в сущности и не можете сделать иначе, то вставьте его в объект.
class Entity
{
private $em;
public function __contruct($em)
{
$this->em = $em;
}
}
Затем вызывается как new Entity($em)
.
Ответ 2
Лучший способ - использовать жизненный цикл: @ORM\HasLifecycleCallbacks
И вы можете использовать соответствующее Событие так, как хотите получить результат:
@postLoad
@postPersist
...
Ответ 3
Вызов диспетчера сущностей изнутри объекта - это плохая практика! Вы должны максимально упростить свои сущности.
Для чего вам нужно вызвать диспетчера сущностей из Entity?
Ответ 4
Я думаю, что вам нужно сделать это, вместо использования Менеджера сущностей внутри вашего объекта, создать пользовательский репозиторий для вашей организации.
В вашем объектном файле ORM добавьте запись следующим образом (или в аннотации класса объекта, если не используете 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
Теперь создайте новый класс PHP, у которого есть пространство имен выше:
//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;
}
}
Наконец, в вашем контроллере:
// 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);
...
}
}
Ответ 5
Вам необходимо установить services.yml:
services:
your_service_name:
class: AppBundle\Controller\ServiceController
arguments: [ @doctrine.orm.entity_manager ]
Вам нужно также установить контроллер со следующим конструктором:
public function __construct(\Doctrine\ORM\EntityManager $em)
{
$this->em = $em;
}
и используйте $this->em
в контроллере
(например, $connection = $this->em->getConnection();
)