Динамический метод find () EntityManager возвращает «таблица не найдена», когда используется пользовательский репозиторий - PullRequest
0 голосов
/ 16 декабря 2018

Сначала я объясню, почему и как работает решение, а затем проблемы, с которыми я столкнулся.Если вы думаете, что есть лучший способ сделать то, что я делаю, я бы хотел это услышать.Я также хотел бы знать, почему доктрина ведет себя таким образом.

Оказывается, мое приложение должно подключаться к другой базе данных в соответствии с клиентом.У меня есть таблица в фиксированной базе данных, содержащая информацию о соединении, которая используется в каком-то запросе.У меня был успех с помощью следующего кода:

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

Я буду очень признателен за любой вклад имысли в этом вопросе.

1 Ответ

0 голосов
/ 16 декабря 2018

Вместо:

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

попробуйте расширить EntityRepository (без использования конструктора) и использовать поиск, как вы это делали в вашем контроллере:

use Doctrine\ORM\EntityRepository;

class ConfigurationRepository extends EntityRepository
{

}

ServiceEntityRepository является необязательным EntityRepository базовый класс с упрощенным конструктором для автопроводки, который явно устанавливает для диспетчера сущностей базовый класс EntityRepository.Поскольку вы не настроили свои менеджеры доктрин для правильной обработки этих соединений (на самом деле это даже невозможно при таком количестве соединений), ServiceEntityRepository передаст неправильный экземпляр EntityManager подклассу EntityRepository, поэтому вам не следует расширять ServiceEntityRepositoryно EntityRepository.

...