Мне трудно понять, как использовать внедрение зависимости. Я перечитал много вопросов / ответов здесь, но я не могу представить это с помощью кода, который я использую.
Model.php
abstract class Model {
protected static function getDB() {
static $db = null;
if ($db === null) {
$db = new PDO('mysql:host=host;dbname=dbname;charset=utf8', 'dbuser', 'password');
}
return $db;
}
}
Model.php просто содержит ту функцию, которую я хочу отойти от установки и вызова статически.
User.php
class User extends Model {
/*
* Selects all of the user information
*/
public function getUser($id){
$db = static::getDB();
$sth = $db->prepare('SELECT * FROM user WHERE id = :id');
$sth->bindValue(':id', $id, PDO::PARAM_INT);
$sth->execute();
return $sth->fetch();
}
/*
* Selects all of the user posts
*/
public function getUserPosts($id){
$db = static::getDB();
$sth = $db->prepare('SELECT * FROM user_posts WHERE user_id = :id');
$sth->bindValue(':id', $id, PDO::PARAM_INT);
$sth->execute();
return $sth->fetch();
}
}
В файле user.php я расширяю класс модели, но я установил $db = static::getDB();
в каждой функции.
Я знаю, что внедрение зависимостей — это просто передача методов / переменных объекту, но я даже не уверен, что делаю это правильно.
Обновлено с дальнейшими мыслями:
Я думаю, что было бы лучше создать закрытую переменную, а в конструкторе мы бы просто вызвать getDB()
вот так:
class User extends Model {
protected $db;
public function __construct(){
$this->db = getDB();
}
/*
* example usage
*/
public function getUser($id){
$sth = $this->db->prepare('SELECT * FROM user WHERE id = :id');
$sth->bindValue(':id', $id, PDO::PARAM_INT);
$sth->execute();
return $sth->fetch();
}
}
Но будет ли он по-прежнему считаться внедрением зависимостей, поскольку я не вызываю класс непосредственно в конструкторе функции?
ВТОРОЕ ОБНОВЛЕНИЕ:
После прочтения нескольких руководств, и это страница что в итоге придало мне больше смысла, это то, что я придумал.
model.php
abstract class Model {
protected $db = null;
public function __construct(){
if($this->db === null){
try {
$this->db = new PDO('mysql:host=' . Config::DB_HOST . ';dbname=' . Config::DB_NAME . '; charset=utf8', Config::DB_USER, Config::DB_PASSWORD);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
return $this->db;
}
}
User.php
class User extends Model {
protected $db;
public function __construct(Model $db){
$this->db = $db;
}
/*
* example usage
*/
public function getUser($id){
$sth = $this->db->prepare('SELECT * FROM user WHERE id = :id');
$sth->bindValue(':id', $id, PDO::PARAM_INT);
$sth->execute();
return $sth->fetch();
}
}
Как это выглядит?
Я думаю, что вы не используете Dependency Injection, потому что вы на самом деле не предоставляете никаких зависимостей в вашу модель, вы генерируете их на конструкторе.
Чтобы предоставить зависимость, вы должны передать ее в качестве аргумента конструктору:
public function __construct($db){
$this->db = $db;
}
Таким образом, вы отделяете создание соединения от вашего класса и можете использовать преимущества внедрения зависимостей, такие как передача объекта Mock для тестирования вместо реальной вещи.
Других решений пока нет …