Bonjour

Ayant suivi les cours de la POO de grafikart, je me retrouve devant une problématique.
Le MVC traditionnel, nous permet de nous conncecter à une seule base de donnée en même temps. Cependant , j'ai deux bases de données contenant chacune la table Posts par exemple. (L'une listant les articles anciens) et l'autre les nouveaux.

Comment puis je modificier la classe mysqlDatatases pour me connecter sur différente bases de données et ensuite l'intégrer dans mes vues.

Cordialement

12 réponses


Salut,

Il suffit de créer 2 instances : une pour ta première BDD et une pour ta seconde, tout simplement ;)
De plus, si je me rappelle bien, il s'agit de singletons donc réutilisable facilement à tout endroit de ton app.
Par contre, je trouve cela bizarre d'avoir deux bases de données.

Attention, si les deux bases sont sur le même serveur, inutile d'aller créer deux instances, une seule suffit pour se connecter. Il faut juste préciser dans ta query le nom de la base avant le nom de la table (ex. SELECT * FROM `ma_bdd`.`ma_table` WHERE `id` = 1;).

Mizzou
Auteur

Bonjour, et merci de vous portez à mon aide,
je vois ce que vous voulez dire, mais dans le pattern MVC de la formation, les fonctions "LoadModel" et "getTable" prennent en paramètre UNE connection à la base Mysql.

On va se tutoyer hein, on est pas chez les aristos ;)

A ce moment là, il te faut faire deux instances, une pour chaque DB.
Peux-tu me montrer le code de la méthode LoadModel stp ?

Mizzou
Auteur

Pour le tutoiement avec plaisir.. Merci
Le but de cette manoeuvre est de pouvoir travailler sur une vue avec l'appel à deux ou X base de données.
La méthode LoadModel est la suivante :

public function LoadModel($model_name){
        $this->$model_name = Application::Instance()->getTable($model_name);
    }

Bon, elle ne m'apprend rien ... je n'ai plus du tout la structure de son code en tête...
A quelle endroit se connecte-on à une base de données (la classe mysqlDatabases je suppose...) ? Peux-tu partager le bout de code correpondant s'il-te-plaît ?

Mizzou
Auteur

Alors le fichier Config retourne un tableau avec toutes les informations concernant les serveurs mysql et j'ai étendu le probleme au cas ou à LDAP, mais je verrais cela plus tard

return [
    'mysql' => [
        'localhost' => [
            'host' => 'localhost',
            'database' => 'Mizzouland',
            'username' => 'root',
            'password' => 'root',
            'charset' => 'utf8'
        ],
        'maman' => [
            'host' => 'plop',
            'database' => 'plop',
            'username' => 'plo3',
            'password' => 'd',
            'charset' => 'utf8'
        ]

    ],

    'ldap' => [

    ]

];

ensuite la class Config est la suivante

namespace Kernel\Config;

class Conf{

    private $settings = [];
    private static $_instance;

    public static function getInstance(){
        if(is_null(self::$_instance)){
            return self::$_instance =  new  Conf();
        }
        return self::$_instance;
    }

    public function __construct(){
        $this->settings = require_once (__DIR__.DS.'Config.php');
    }

    public function get($key, $host){
        return $this->settings[$key][$host];
    }

    public function getAll($key){
        return $this->settings[$key];
    }

ensuite la class mysql est la suivante

namespace Kernel\Database;
use \PDO;
use Kernel\Config\Conf;

class MysqlDatabase extends BaseDatabase{

    private $testConfig;
    private $testPdo;
    private $serverChoice = 'localhost';
    private $config;

    public function __construct($server_name) {
        $this->serverChoice = $server_name;
    }

    private function MysqlDB(){
        $key = $this->serverChoice;
        $this->testConfig = Conf::getInstance()->get('mysql', $key);

        if($this->testPdo === NULL){
            $pdo = new PDO ("mysql:dbname={$this->testConfig['database']};host={$this->testConfig['host']}", $this->testConfig['username'], $this->testConfig['password']);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->testPdo = $pdo;
        }

        return $this->testPdo;
    }

la class application qui gere un peu tout

use Kernel\Database\MysqlDatabase;
use Kernel\Core\Main;

class Application{

    public $dB;
    protected static $title = 'DASHBOARD  ';
    public static $_instance;

    /**
     * SINGLETON QUI PERMET DE RECUPERER UNE SEULE ET MEME INSTANCE DE LA CLASS APPLICATION
     * @return 
     */
    public static function Instance(){
        if(is_null(self::$_instance)){
            self::$_instance = new Application();
        }
        return self::$_instance;
    }

    /**
     * UTILISATION DES FACTORY PERMETTANT D'INSTANCIER LA CLASSE QUE L'ON SOUHAITE 
     */
    public function getTable($name){
        $class = '\\App\Tables\\'.ucfirst($name).'Table';
        return new $class($this->getDB());
    }

et pour terminer le baseController

namespace Kernel\Controller;

use Application;

class BaseController{
    protected $viewPath;
    protected $template;
    protected $rendered = FALSE;

    public function Render($view, $variables = []){
        if($this->rendered){
            $this->rendered = FALSE;
        }
        ob_start();
        $view = str_replace('.', '/', $view).'.php';
        extract($variables);
        require $this->viewPath.DS.$view;
        $Content_For_Layout = ob_get_clean();

        if($this->template == 'Admin'){
            $this->template = 'Admin'.DS.$this->template;
        }

        require ($this->viewPath.DS.'Layout'.DS.ucfirst($this->template).'.php');
        $this->rendered = TRUE;
    }

    public function LoadModel($model_name){
        $this->$model_name = Application::Instance()->getTable($model_name);
    }

L'idée si elle est bonne est la suivante:

namespace App\Controller;

class PostsController extends AppController{

    public function __construct() {
        parent::__construct();
        $this->LoadServer('localhost');
        $this->LoadServer('TOTO');
        $this->LoadModel('Post');
    }

    public function home(){
        $post_1 = $this->localhost()->Post()->FindAll();
        $post = $this->TOTO->Post->FindAll();
        $this->Render('posts.home', compact('post', 'post_1'));
    }

ENFIN ce serai mon ideal, à moins que vous ayez autre chose à me proposer.
MERCI

Où est le problème ? Lorsque tu instancies la classe MysqlDatabase, tu choisis quelle DB tu veux taper non ? Donc tu peux créer 2 instances, une pour chaque BDD, non ?

Mizzou
Auteur

j'ai oublie la fonction getDB dans la class Application

 public function getDB(){
        if($this->dB === NULL){
            $this->dB = new MysqlDatabase();
        }
        return $this->dB;
    }

le tuto nous fait instancier la classe MysqDatabase uniquement avec la fonction au dessus, et moi j'ai mis en paramètre

public function getDB($server_name){
        if($this->dB === NULL){
            $this->dB = new MysqlDatabase($server_name);
        }
        return $this->dB;
    }

mais cela ne change pas le probleme, il faut que je change pas fonction loadModel en fonction de mysql(), mais je pensais que cela
Car si je rajoute un paramètre à la class LoadModel

public function LoadModel($model_name, $serveur){
        $this->$model_name = Application::Instance()->getTable($model_name, $serveur);
    }

il ne me creer pas deux instances, mais uniquement la premiere

C'est parceque il te faut un tableau d'instance et tu peux mettre en clef le nom de la connection et en valeur la connection elle-même
ensuite c'est du get($name) en fonction de ce que tu veux.

Mizzou
Auteur

Je ne connais pas du tout ce terme.. de tableau d'instance. En gros cela veut dire que je stocke mes différentes instance pdo dans un tableau?

Oui en gros c'est l'idée. Et tupeux y accéder via la clef du tableau.

Mizzou
Auteur

Oki, je devrais donc effectuer cette fonction dans le mysqlDatabase