I'm working on a very unorganized (no tests, logic mixed in everywhere) PHP application. I started reading the book Modernizing Legacy Applications In PHP and am now in the position where I need to replace global
variables.
In my case we have both MySQL and MongoDB mixed heavily throughout the application using global variables: $database
for MySQL and $mongo
for MongoDB. I'm wondering what the best way to inject both of these databases would be. Most examples (in the book and elsewhere) have something like this:
class Database {
public function __construct() {}
}
class MySQL extends Database {
private $mysql;
public function __construct() {
$default_options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
// get config from file
$this->mysql = new PDO(...);
}
public function get_instance() { return $this->mysql; }
}
class MongoDB extends Database {
private $mongodb;
public function __construct() {
// get config from file
$mongodb = new MongoClient(...);
}
public function get_instance() { return $this->mongodb; }
}
class User {
private $database = null;
private $table = "users";
public function __construct(Database $database) {
$this->database = $database;
}
}
// In another file:
$user = new User(new \Database\MySQL);
That's cool, but the problem I'm having is, when User
stores its attributes like name
,email
, id
, etc. in MySQL, and it stores something else like user_type
in Mongo (obviously its more than this but I'm just giving an easy example), than how does dependency injection work?
Do I have to pass in two Database
classes to the constructor?
Do I have a set_database
function that I have to keep switching between when I want to make a call?
class User {
private $database = null;
private $table = "users";
public function __construct(Database $database) {
$this->database = $database;
}
public function get_user() {
$first_set = $this->database->run('select * from users',[]);
$this->database->set_database(new \Database\MongoDB);
$second_set = $this->database->run('users',[]);
}
}
I'm trying to understand how this would work, and would continue working if other developers added databases that had to be called in the User
class (like Redis for example).