IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Doctrine2 PHP Discussion :

Changer de base de manière dynamique et à la volée


Sujet :

Doctrine2 PHP

  1. #1
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut Changer de base de manière dynamique et à la volée
    Bonjour à tous,

    Après 2 jours de recherches infructueuses je me décide à vous consulter concernant mon problème car ce que je veux faire ne me semble pas si compliqué ni complètement extravagant mais je n'arrive pas à trouver de pistes qui pourraient m'aider.

    Je vous expose mon problème.
    J'ai une base de donnée centrale dans laquelle je stock mes utilisateurs et pour chacun d'eux le nom de la base client sur laquelle l'application de se connecter ensuite pour avoir accès aux données de l'utilisateur en question.

    Donc je configure dans mon config.yml l'accès à la base centrale qui est toujours le même.
    Je fait une requête sur cette base pour récupérer pour récupérer les infos de connexion à la base client.

    J'ai réussi au cours de mes investigations à trouver un script qui permet de passer d'une base à une autre. J'ai donc créé un service avec ce script afin de pouvoir l'appeler dès que j'en ai besoin. Car malheureusement le changement de connexion ne persiste pas il faut donc faire appel au service avant chaque appel à mon entitymanager.

    La ou ça se complique c'est que je souhaite utiliser le FOSUserBundle pour la gestion de mes utilisateurs mais que je ne peux pas faire appel a mon service avant de lancer la vérification de l'utilisateur. Ce qui fait que lorsque je remplis mon formulaire de login il fait la recherche sur la base centrale alors que les mots de passe utilisateurs sont stockés dans les bases client.

    J'ai aussi vu que l'on pouvait surcharger les méthodes de connexion en les déplaçant directement dans le repository de mon entité utilisateur (notamment la méthode : "loadUserByUsername()").
    Mais je n'arrive pas à appeler mon service de switch de base depuis un repository.

    Alors mes questions sont les suivantes :
    Comment faire en sorte que la connexion soit conservé une fois que la bascule a été faite une première fois ?
    OU
    Comment appeler un service dans un repository ?
    OU
    Une autre idée ?

    Merci d'avance.

  2. #2
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    tu peux faire autant de connexion que tu veux sur différentes bases, il suffit de bien mettre tout ça sous connections, donc pas besion de "script" ni rien

  3. #3
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Oui je sais bien mais je peux avoir des centaines de base clients et je ne connait pas leur nom à l'avance.
    Mon idée était de ne pas avoir un fichier config.yml qui soit immense et de ne pas avoir besoin de le modifier à chaque fois qu'une nouvelle base client sera crée, ce qui risque d'arriver très fréquemment.

  4. #4
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    comment sont crées les bases ?

  5. #5
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    et bien en fait chaque nouveau client sera créé via une "super admin" qui sera calé sur la base centrale.

    Une fois que le nouveau client sera créé une base sera générée suivant un modèle. Mais pour l'instant ce processus n'est pas en place. Chaque base est générée à la main.

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    si chaque base est créer a la main, autant change le config.yml à la main aussi, de tout facon t'en que y'a pas d'automatisation tu pourras pas faire grand chose

  7. #7
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Oui mais le système va être automatisé très vite car il faut que des non techniciens puisse rajouter des clients aussi, sans avoir a mettre les mains dans le code.
    J'aimerais donc que mon dev soit déjà prêt pour ça.

  8. #8
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    ça sera faire au moment de l'automatisation alors. dans tout les cas le fichiers seras a remplir, automatiquement ou pas via des données, donc tu automatisation a juste a remplir le config.yml ou a creer d'autre fichier de confier charger par un service

  9. #9
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Il n'y a pas d'autre moyen de faire que de passer par le fichier de config ?

  10. #10
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    Citation Envoyé par anta_res Voir le message
    Il n'y a pas d'autre moyen de faire que de passer par le fichier de config ?
    Il faut bien que les infos soit quelque part, en base ça doit être faisable

  11. #11
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Oui cela m'arrangerais franchement que ces infos soient stockées en base et pouvoir créer des connections à partir de ces infos.

    Sinon je vais me pencher sur la génération de fichiers config annexes que je vais essayer de charger avec un service comme tu le propose.

  12. #12
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    tu pourras faire ca dans la méthode boot de ton bundle

  13. #13
    Membre habitué Avatar de anta_res
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 93
    Points : 173
    Points
    173
    Par défaut
    Bon je crois être sur la bonne voie.
    J'ai créé un provider personnalisé dans lequel j'ai rajouté ma fonction pour le changement de connexion.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
     
    namespace SocleCommun\AuthentificationBundle\Security;
     
    use Symfony\Component\Security\Core\User\UserProviderInterface;
    use Symfony\Component\Security\Core\User\UserInterface;
    use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
    use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
     
    use Symfony\Bundle\DoctrineBundle\Registry;
     
    class AuthentificationProvider implements UserProviderInterface{
     
        protected $doctrine;
        protected $dbUser;
        protected $dbPass;
     
        public function __construct(Registry $doctrine,$dbUser,$dbPass){
            $this->doctrine = $doctrine;
            $this->dbUser = $dbUser;
            $this->dbPass = $dbPass;
        }
     
        private function switchDatabase($dbName='', $dbIp=''){
     
            $paramDb['nomBase'] = $dbName;
            $paramDb['hostBase'] = $dbIp;
     
            $connection = $this->doctrine->getConnection('dynamique');
     
            $connection->close();
     
            $refConn = new \ReflectionObject($connection);
            $refParams = $refConn->getProperty('_params');
            $refParams->setAccessible('public');
     
            $params = $refParams->getValue($connection);
            $params['dbname'] = $dbName;
            $params['user'] = $this->dbUser;
            $params['password'] = $this->dbPass;
            $params['host'] = $dbIp;
     
            $refParams->setAccessible('private');
            $refParams->setValue($connection, $params);
     
            $this->doctrine->resetEntityManager('dynamique');
     
        }
     
        public function loadUserByUsername($username){
            $q1 = $this->doctrine->getEntityManager()
                ->getRepository('SocleCommunAuthentificationBundle:config_client')
                ->findOneByIdentifiant($username);
            $this->switchDatabase($q1->getNom_base(),$q1->getIpServeurPrive());
     
            $q = $this->doctrine
                ->getEntityManager('dynamique')
                ->createQuery('
                    SELECT u FROM SocleCommunAuthentificationBundle:utilisateur u
                    WHERE u.username = :identifiant
                    OR u.email = :email')
                ->setParameters(array(
                    'identifiant' => $username,
                    'email' => $username,
                ));
            try {
                $user = $q->getSingleResult();
            } catch (NoResultException $e) {
                throw new UsernameNotFoundException(sprintf('Unable to find an active admin AcmeUserBundle:User object identified by "%s".', $username), null, 0, $e);
            }
            return $user;
        }
     
        public function refreshUser(UserInterface $user){
            $class = get_class($user);
            if (!$this->supportsClass($class)) {
                throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $class));
            }
     
            return $this->loadUserByUsername($user->getUsername());
        }
     
        public function supportsClass($class){
            return $this->getEntityName() === $class || is_subclass_of($class, $this->getEntityName());
        }
    }
    Ce provider est déclaré comme un service comme indiqué dans la doc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        Authentification_provider:
            class: SocleCommun\AuthentificationBundle\Security\AuthentificationProvider
            arguments: [@doctrine,%dbClientUser%,%dbClientPass%]
    Cela fonctionne presque car le système me considère comme authentifié comme on peux le voir dans la tool bar sur la capture ci dessous. Mais j'ai quand même une erreur que je n'arrive pas a comprendre.



    Si certain d'entre vous on des pistes je suis preneur.

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Février 2012
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 116
    Points : 85
    Points
    85
    Par défaut
    Je ne sais pas si cela peut aider :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
     // Get domain from url
     $domainUrl = $_SERVER['HTTP_HOST'];
     
     // Test if there's "www." in the start of domain url
     // And remove "www."
     if(substr($domainUrl,0,4) == "www.")
     {
           $domain = substr($domainUrl, 4 , strlen($domainUrl));
     }
     
      // Get website database name
      $em = $this->container->get('doctrine')->getEntityManager();
      $website= $em->getRepository('XxxXxxxBundle:Website')->findOneByDomain($domain);
      $db = $website->getSegment().'_'.$website->getDomain();
     
      // connect to tenant database
      $connectionFactory = $this->container->get('doctrine.dbal.connection_factory');
      $connection = $connectionFactory->createConnection(array(
                  'driver' => $this->container->getParameter('database_driver'),
                  'user' => $this->container->getParameter('database_user'),
                  'password' => $this->container->getParameter('database_password'),
                  'host' => $this->container->getParameter('database_host'),
                  'dbname' => $db,
              ));
     
    if(!$connection)
    { 
            throw $this->createNotFoundException($this->get('translator')->trans('website.notfound', array('%domain%' => $domainUrl )) );
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 30/08/2010, 15h51
  2. Réponses: 13
    Dernier message: 25/01/2007, 17h20
  3. Réponses: 1
    Dernier message: 11/01/2007, 22h57
  4. [JTable] Changer les colonnes de manière dynamique
    Par gg2laba dans le forum Composants
    Réponses: 3
    Dernier message: 03/10/2005, 23h39
  5. Réponses: 8
    Dernier message: 17/10/2004, 15h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo