动态 EntityManager find () 方法 returns "table not found" 当自定义存储库正在使用时
Dynamic EntityManager find () method returns "table not found" when a custom repository is in use
首先,我将解释该解决方案的工作原理和工作原理,然后是我遇到的问题。如果您认为有更好的方法来完成我的工作,我很乐意听取您的意见。我也想知道为什么学说会这样。
原来我的应用程序需要根据客户端连接到不同的数据库。我在固定数据库中有一个 table,其中包含在某些请求中使用的连接信息。
我已成功使用以下代码:
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());
}
}
如您所见,我 return 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());
}
}
它按预期工作或者我相信直到我看到当实体有一个自定义存储库时它无法使用动态连接因此以前的路由将 return 和 table 不发现异常。
- @ORM\Entity() <-- Works like a charm
- @ORM\Entity(repositoryClass="App\Repository\ConfigurationRepository")<-- Table not found.
如果我再次创建连接,它会在存储库中工作,尽管我不喜欢该解决方案。那么,我想要什么?我希望能够使用 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();
}
我将非常感谢在这件事上的任何贡献和想法。
而不是:
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
基础 class,具有用于自动装配的简化构造函数,它显式地将实体管理器设置为 EntityRepository
基础 class .由于您没有配置您的学说管理器来正确处理这些连接(实际上有这么多连接是不可能的),ServiceEntityRepository
会将错误的 EntityManager 实例传递给 EntityRepository
subclass,这就是为什么你不应该扩展 ServiceEntityRepository
但 EntityRepository
.
首先,我将解释该解决方案的工作原理和工作原理,然后是我遇到的问题。如果您认为有更好的方法来完成我的工作,我很乐意听取您的意见。我也想知道为什么学说会这样。
原来我的应用程序需要根据客户端连接到不同的数据库。我在固定数据库中有一个 table,其中包含在某些请求中使用的连接信息。 我已成功使用以下代码:
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());
}
}
如您所见,我 return 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());
}
}
它按预期工作或者我相信直到我看到当实体有一个自定义存储库时它无法使用动态连接因此以前的路由将 return 和 table 不发现异常。
- @ORM\Entity() <-- Works like a charm
- @ORM\Entity(repositoryClass="App\Repository\ConfigurationRepository")<-- Table not found.
如果我再次创建连接,它会在存储库中工作,尽管我不喜欢该解决方案。那么,我想要什么?我希望能够使用 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();
}
我将非常感谢在这件事上的任何贡献和想法。
而不是:
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
基础 class,具有用于自动装配的简化构造函数,它显式地将实体管理器设置为 EntityRepository
基础 class .由于您没有配置您的学说管理器来正确处理这些连接(实际上有这么多连接是不可能的),ServiceEntityRepository
会将错误的 EntityManager 实例传递给 EntityRepository
subclass,这就是为什么你不应该扩展 ServiceEntityRepository
但 EntityRepository
.