1

In my Symfony 3.4 project I got several databases which are managed by one entity manager. Consider the following code:

config.yml

doctrine:
dbal:
    default_connection:       default
    connections:   
        dynamic:
            driver:   pdo_mysql
            host:     "%database_host%"
            port:     "%database_port%"
            dbname:   "%database_name_dynamic%"
            user:     "%database_user%"
            password: "%database_password%"
            charset:  UTF8 
            wrapper_class: 'AppBundle\Connection\ConnectionWrapper'    
orm:
    default_entity_manager:   default
    auto_generate_proxy_classes: "%kernel.debug%"
    entity_managers:   
        dynamic:
            connection:       dynamic
            auto_mapping:     false
            mappings:
                DynamicBundle: ~
            naming_strategy:  doctrine.orm.naming_strategy.underscore  

AppBundle\Connection\ConnectionWrapper

<?php

namespace AppBundle\Connection;

use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\Session\Session;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Driver;

class ConnectionWrapper extends Connection
{

/**
* @var array
*/
private $params = [];

/**
 * @var bool
 */
private $_isConnected = false;

public function __construct(array $params, Driver $driver, $config, $eventManager)
{
    $this->params['dbname'] = $params['dbname'];
    $this->params['user'] = $params['user'];
    $this->params['password'] = $params['password'];
    parent::__construct($params, $driver, $config, $eventManager);
}

public function forceSwitch($dbName, $dbUser, $dbPassword)
{
$this->params['dbname'] = $dbName;
$this->params['user'] = $dbUser;
$this->params['password'] = $dbPassword;

 if ($this->isConnected()) {
    $this->close();
  }
}

/**
 * {@inheritDoc}
 */
public function connect()
{

  if ($this->isConnected()) {
    return true;
  }

$driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array();

$params = $this->getParams();
$params['dbname'] = $this->params['dbname'];

$this->_conn = $this->_driver->connect($params, $this->params['user'], $this->params['password'], $driverOptions);

if ($this->_eventManager->hasListeners(Events::postConnect)) {
    $eventArgs = new ConnectionEventArgs($this);
    $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs);
}

 $this->_isConnected = true;

 return true;
}

/**
 * {@inheritDoc}
 */
public function isConnected()
{
    return $this->_isConnected;
}

/**
 * {@inheritDoc}
 */
public function close()
  {
    if ($this->isConnected()) {
        parent::close();
        $this->_isConnected = false;
  }
 } 
}

Services.yml

app.handler.session_idle:
        class: AppBundle\EventListener\RequestListener
        arguments: ["@doctrine.orm.dynamic_entity_manager"]
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

AppBundle\EventListener\RequestListener

namespace AppBundle\EventListener;

use Doctrine\ORM\EntityManager;

class RequestListener{
    protected $entityManager;
    public function __construct(EntityManager $entityManager){
       EntityManager $entityManager
    }

    public function onKernelRequest(GetResponseEvent $event){
     $em = $this->entityManager;
    }
}

The purpose of ConnectionWrapper class is to switch the database once the app is loaded depending on user logged in (every user has its own DB).

But when I try to load my app with dynamic_entity_Manager I get the following error:

Uncaught PHP Exception Doctrine\DBAL\Exception\ConnectionException: "An exception occurred in driver: SQLSTATE[HY000] [1045] Access denied for user ''@'192.168.208.1' (using password: NO)" at /var/www/html/public/dev/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php line 93 

If I use default entity manager everything works fine, even dynamic entity manager is accessible. Any ideas how to fix the error would be welcome. Thank you.

UPD_1

In THIS question it is said to inject a Doctrine\Common\Persistence\ManagerRegistry but I need to put it into services.yml declaration. Any ideas how to do that? Thank you.

Masha
  • 827
  • 1
  • 10
  • 30

0 Answers0