22

我想使用,例如:

$em = $this->getEntityManager();

在实体内部。

我知道我应该将其作为一项服务来执行,但出于某些测试目的,我想从实体访问它。

有可能实现吗?

我试图:

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

但不工作。

致命错误:在第449行 的/opt/lampp/htdocs/web/src/Pct/bundle/Entity/User.php中调用未定义的方法 Proxies\webBundleEntityUserProxy::getEntityManager()

为什么我要这样做?

我有 3 种用户:Facebook、Twitter 和 MyOwnWebsite 用户。他们每个人都有不同的头像,链接 facebook 的个人资料、twitter 或其他,如果它的 myownwebsite 用户,我从数据库中的 URL 检索头像。现在,我不想创建服务,因为我只是想让它工作,测试它,而不是创建最终部署。所以这就是我尝试从实体调用实体管理器的原因。我现在不想修改配置文件,只是这个实体。

4

5 回答 5

32

正如评论者(再次)指出的那样,实体内部的实体管理器是代码异味。对于 OP 的特定情况,他希望以最少的麻烦获得实体管理器,简单的 setter 注入将是最可靠的(与我通过构造函数注入的原始示例相反)。

对于最终在这里寻找相同问题的卓越解决方案的任何其他人,有两种方法可以实现这一目标:

  1. 按照https://stackoverflow.com/a/24766285/1349295的建议实现ObjectManagerAware接口

    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. 或者,使用@postLoad/@postPersist生命周期回调并使用https://stackoverflow.com/a/23793897/1349295LifecycleEventArgs建议的参数获取实体管理器

    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;
    }
}

然后调用 as new Entity($em)

于 2013-02-04T10:42:02.207 回答
6

最好的方法是使用生命周期:@ORM\HasLifecycleCallbacks

您可以根据需要使用适当的事件来获得结果:

@postLoad
@postPersist
...
于 2014-05-21T21:13:33.800 回答
4

从实体内部调用实体管理器是一种不好的做法!您应该使您的实体尽可能简单。

出于什么目的,您需要从实体调用实体管理器?

于 2013-02-04T10:29:22.640 回答
2

我认为您应该做的是,而不是在您的实体中使用实体管理器,而是为您的实体创建一个自定义存储库。

在您的实体 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);
         ...

      }
   }
于 2016-11-06T17:21:13.403 回答
0

您需要将 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();

于 2016-02-18T09:38:28.753 回答