Сначала я объясню, почему и как работает решение, а затем проблемы, с которыми я столкнулся.Если вы думаете, что есть лучший способ сделать то, что я делаю, я бы хотел это услышать.Я также хотел бы знать, почему доктрина ведет себя таким образом.
Оказывается, мое приложение должно подключаться к другой базе данных в соответствии с клиентом.У меня есть таблица в фиксированной базе данных, содержащая информацию о соединении, которая используется в каком-то запросе.У меня был успех с помощью следующего кода:
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 () <- Работает как шарм </li>
- @ ORM \ Entity (repositoryClass = "App \ Repository\ ConfigurationRepository ") <- Таблица не найдена. </li>
Это работает в репозитории, если я снова создаю соединение, хотя мне не нравится решение.Итак, что я хочу?Я хотел бы иметь возможность использовать основные методы, такие как 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();
}
Я буду очень признателен за любой вклад имысли в этом вопросе.