2

Each connected member of my site has its database. Here is the doctrine config for "user_1":

return array(
'doctrine' => array(
    'connection' => array(
        'orm_default' => array(
            'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
            'params' => array(
                'host'     => 'localhost',
                'port'     => '3306',
                'user'     => 'user_1',
                'password' => 'psswd_user_1',
                'dbname'   => 'database_user_1',
                'charset' => 'utf8',
                'driverOptions' => array (1002 => 'SET NAMES utf8'),
            )),),),);

Is there a way to replace : 'user_1', 'psswd_user_1' and 'database_user_1' with 'user_x', 'psswd_user_x' and 'database_user_x' for user_x ?

I don't know how to do that ! I'd like to avoid copying the same code for each user ...

Thank you for help

2 Answers2

1

The proper way to do this might be to inject the configuration that you need when the connection is created. I couldn't find any event that you could hook into to do that, so you have to find the right service manager key to override.

With a little bit of source code digging, I found that these options are sent to a DoctrineORMModule\Options\DBALConnection instance and that this instance is created by DoctrineORMModule\Service\DBALConnectionFactory

You need to override this factory with something like this:

<?php
namespace MyModule\Service;
use DoctrineORMModule\Service\DBALConnectionFactory;
use Zend\ServiceManager\ServiceLocatorInterface;

class MyDBALConnectionFactory extends DBALConnectionFactory
{

    public function getOptions(ServiceLocatorInterface $sl, $key, $name = null)
    {
        $options = parent::getOptions($sl, $key, $name);

        // override for everyone that needs a DBALConnection
        if ($this->getOptionClass() === 'DoctrineORMModule\Options\DBALConnection') {

             // set custom parameters here
             // maybe fetch the current user with $sl->get('...')
             $params = [/* ... */];
             $options->setParams($params);
        }

        return $options;
    }
}

And then you just tell the service manager about it:

<?php 
return [
    ...
    'doctrine' => [
        'doctrine_factories' => [
            'connection' => 'MyModule\Service\DBALConnectionFactory',
        ]
    ]
    ...
];
Clément Prévost
  • 8,000
  • 2
  • 36
  • 51
0

Thanks to Alejandro Celaya. 1st link and 2d link

I hope it will be useful. I know it's not perfect but I can't do better ! I'd like critical.

in config/autoload/doctrine.local.php:

'doctrine' => array(
'connection' => array(
    'orm_default' => array(
        'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
        'params' => array(
            'host'     => 'localhost',
            'port'     => '3306',
            'user'     => 'root',
            'password' => '',
            'dbname'   => 'gestion_toto_default',
            'charset' => 'utf8',
            'driverOptions' => array(1002 => 'SET NAMES utf8'),
        )
    ),
    'orm_toto_users' => array(
        'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
        'params' => array(
            'host'     => 'localhost',
            'port'     => '3306',
            'user'     => 'root',
            'password' => '',
                 //gestion_toto_users has 2 tables : users and db_users
            'dbname'   => 'gestion_toto_users', 
            'driverOptions' => array(1002 => 'SET NAMES utf8'),
        )
    ),
    'dynamic_orm' => array(
        'driverClass' =>'Doctrine\DBAL\Driver\PDOMySql\Driver',
        'params' => array(
            'host'     => 'localhost',
            'port'     => '3306',
            'user'     => '',
            'password' => '',
            'dbname'   => '',
            'driverOptions' => array(1002 => 'SET NAMES utf8'),
        ),
    ),
),

'driver' => array(
    'orm_toto_users' => array(
        'class'   => 'Doctrine\ORM\Mapping\Driver\DriverChain',
        'drivers' => array(
            __NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
        )
    ),
    'dynamic_orm' => array(
        'drivers' => array(
            __NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
        )
    ),
),

'entitymanager' => array(
    'orm_toto_users' => array(
        'connection'    => 'orm_toto_users',
        'configuration' => 'orm_default'
    ),
    'dynamic_orm' => array(
        'connection' => 'dynamic_orm',
    ),
),

'eventmanager' => array(
    'orm_toto_users' => array()
),

'sql_logger_collector' => array(
    'orm_toto_users' => array(),
),

'entity_resolver' => array(
    'orm_toto_users' => array()
),),

module.config.php :

    'doctrine' => array(
    'driver' => array(
        __NAMESPACE__ . '_driver' => array(
            'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
            'cache' => 'array',
            'paths' => array(
                __DIR__ . '/../src/' . __NAMESPACE__ . '/Entity'
            ),
        ),
        'orm_default' => array(
            'drivers' => array(
                __NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
            )
        ),
    ),
    'authentication' => array(
        'orm_default' => array(
            'object_manager' => 'doctrine.entitymanager.orm_toto_users',
            'identity_class' => 'MyModule\Entity\User',
            'identity_property' => 'identifiant',  
            'credential_property' => 'password', 
            'credential_callable' => function(\MyModule\Entity\User $user, $passwordGiven) {
                $bcrypt   = new \Zend\Crypt\Password\Bcrypt();
                return $bcrypt->verify($psswdGiven, $user->getPsswd()) && $user->getIsactif();
            },
        ),
    ),
),

in Xcontroller :

    public function getEntityManager()
{
    if (null === $this->em) {

        $this->em = $this->getServiceLocator()->get('dynamic_entity_manager');
    }
    return $this->em;
}

in userController :

    public function getEntityManager()
{
    if (null === $this->em) {
        $this->em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_toto_users');
    }
    return $this->em;
}

in DynamicEMFactory.php:

class DynamicEMFactory implements FactoryInterface {
public function createService(ServiceLocatorInterface $serviceLocator)
{
        // Get current user
    $authService = $serviceLocator->get('Zend\Authentication\AuthenticationService');
    if (! $authService->hasIdentity()) {
        throw new \RuntimeException(
            'It is not possible to create a dynamic entity manager before a user has logged in'
        );
    }

    $user = $authService->getIdentity();
    $db_User = $user->getUser_db()->getDbuser();
    $db_Psswd = $user->getUser_db()->getDbpsswd();
    $db_Name = $user->getUser_db()->getDbname();

        // Update connection config
    $globalConfig = $serviceLocator->get('config');
    $globalConfig['doctrine']['connection']['dynamic_orm']['params']['user'] = $db_User;
    $globalConfig['doctrine']['connection']['dynamic_orm']['params']['password'] = $db_Psswd;
    $globalConfig['doctrine']['connection']['dynamic_orm']['params']['dbname'] = $db_Name;

    $isAllowOverride = $serviceLocator->getAllowOverride();
    $serviceLocator->setAllowOverride(true);
    $serviceLocator->setService('config', $globalConfig);
    $serviceLocator->setAllowOverride($isAllowOverride);

    return $serviceLocator->get('doctrine.entitymanager.dynamic_orm');
}

}

in module.config :

    'service_manager' => array(
    'factories' => array(

        'dynamic_entity_manager' => 'XXX\Service\Factory\DynamicEMFactory',

in onBootstrap (to change appearence):

    $authService = $serviceManager->get('Zend\Authentication\AuthenticationService');
    if ($authService->getIdentity()) {
        $em = $serviceManager->get('dynamic_entity_manager');
    } else {
        $em = $serviceManager->get('doctrine.entitymanager.orm_default');
    }
    $viewModel = $e->getApplication()->getMvcEvent()->getViewModel();
    $query = $serviceManager->get('param_user');
    $tab = $query->getReponse($em);
    $nom_theme = $tab['something']));
    $viewModel->nom_theme = $nom_theme;//to layout