Подтвердить что ты не робот

Получить 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. Сейчас я не хочу изменять файлы конфигурации, только этот объект.

4b9b3361

Ответ 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();)