首页 > 解决方案 > 使用自定义存储库时,动态 EntityManager find() 方法返回“未找到表”

问题描述

首先,我将解释解决方案的工作原理和方式,然后解释我遇到的问题。如果您认为有更好的方法来做我所做的事情,我很想听听。我也想知道为什么教义会这样。

事实证明,我的应用程序需要根据客户端连接到不同的数据库。我有一个固定数据库中的表,其中包含在某些请求中使用的连接信息。我使用以下代码取得了成功:

class DynamicEntityManager {

protected $em;
private $request;

private $client_id;

public function __construct(RequestStack $request, EntityManagerInterface $em){
    $this->em = $em;
    $this->request = $request;
}

public function getEntityManager(ClientConn $client = null) {
    $request = $this->request->getCurrentRequest();  
    if($client == NULL){
        $domain = $request->attributes->get('domain');
        if($domain == "" || $domain == NULL){
            throw new \Exception("Error de conexion", 1);
        }
        $client = $this->em->getRepository(ClientConn::class)->findOneBy(array(
            "subdomain" => $domain
        ));
        if($client == NULL){
            throw new \Exception("Error de conexion", 1);                
        }
    }
    $connectionDB = $client->getConnection();
    $dbdriver = 'oci8';
    $conexionSplit = explode(':',$connectionDB);
    $dbhost = $conexionSplit[0];
    $dbport = $conexionSplit[1];
    $dbname = $conexionSplit[2];
    $dbuser = $client->getUsuarioBd();
    $dbpass = $client->getClaveBd();
    $service = false;

    $this->client_id = $client->getId();

    if(strpos($dbname,'SN=') !== false){
        $parts = explode('=',$dbname);
        $dbname = $parts[1];
        $service = true;
    }

    $request->attributes->set('client_id',$client->getId());

    $conn = array(
        'driver'    => $dbdriver,
        'host'      => $dbhost,
        'port'      => $dbport,
        'dbname'    => $dbname,
        'user'      => $dbuser,
        'password'  => $dbpass,
        'service'   => $service,
        'charset'   => 'UTF8',
        'schema'    => null
    );
    return EntityManager::create($conn, $this->em->getConfiguration());
    }
}

如您所见,我使用新连接返回EntityManager::create($conn, $this->em->getConfiguration ())。我使用它的方式是下一个:

 /**
 * @Route("/api/client/{id}/conf/{confID}", name="conf.show")
 * @Method({"GET"})
 */
public function show(ClientConn $client, Request $request, DynamicEntityManager $dem ,$confId){
    try {

        $em = $dem->getEntityManager($client);
        $entity = $em->getRepository(Configuration::class)->find($confId);
        return new JsonResponse($entity, 200);
    }
    catch(\Exception $ex) {
        return new JsonResponse([
            "excepcion" => $ex->getMessage()
        ], $ex->getCode());
    }
}

它按预期工作,或者我相信直到我看到当实体具有自定义存储库时它无法使用动态连接,因此之前的路由将返回一个未找到表的异常。

  • @ORM\Entity() <-- 像魅力一样工作
  • @ORM\Entity(repositoryClass="App\Repository\ConfigurationRepository")<-- 找不到表。

如果我再次创建连接,它可以在存储库中工作,尽管我不喜欢这个解决方案。那么,我想要什么?我希望能够使用 find()、findBy() 等基本方法,而不必每次使用自定义存储库时都重写它们。

class ConfigurationRepository extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry, DynamicEntityManager $dem)
{
    parent::__construct($registry, Configuration::class);
    $this->dem= $dem;
}

public function uglyFind($client, $confID)
{        
    $query = $this->dem->getEntityManager($client)->createQueryBuilder('conf')
    ->select("conf")
    ->from(ConfPedidosLentes::class,'conf')
    ->where('conf.id = :value')->setParameter('value', $confID)
    ->getQuery();

    return $query->getOneOrNullResult();
}

我将非常感谢在这件事上的任何贡献和想法。

标签: symfonydoctrinesymfony4

解决方案


代替:

class ConfigurationRepository extends ServiceEntityRepository
{
    public function __construct(RegistryInterface $registry, DynamicEntityManager $dem)
    {
        parent::__construct($registry, Configuration::class);
        $this->dem= $dem;
    }
    ...

尝试扩展 EntityRepository (不使用构造函数)并像在控制器中那样使用 find :

use Doctrine\ORM\EntityRepository;

class ConfigurationRepository extends EntityRepository
{

}

ServiceEntityRepository是一个可选的EntityRepository基类,具有用于自动装配的简化构造函数,它将实体管理器显式设置为EntityRepository基类。由于您没有配置您的学说管理器来正确处理这些连接(实际上甚至不可能有这么多的连接),ServiceEntityRepository会将错误的 EntityManager 实例传递给EntityRepository子类,这就是您不应该扩展ServiceEntityRepositorybut的原因EntityRepository


推荐阅读