Внедрение зависимостей для класса с массивом объектов в качестве атрибута класса

Я новичок в программировании ООП на php и пытаюсь понять и реализовать функцию внедрения зависимостей в моем проекте MVC. Далее я объясню супер простой пример функции, в которой я пытаюсь применить внедрение зависимости. Реальное приложение намного сложнее, но этого должно быть достаточно, чтобы продемонстрировать проблему, с которой я столкнулся.

Я создал модель под названием «пользователь», которая отвечает за управление одним пользователем. Данные, обрабатываемые классом (данные о пользователе), также сохраняются в таблице базы данных. Класс «пользователь» имеет метод для загрузки и сохранения / обновления данных в таблице базы данных. Пользовательский класс может быть инициирован данными, загруженными из базы данных (с использованием идентификатора пользователя), или загрузкой из массива, предоставленного конструктору.

Проект имеет дело с несколькими пользователями одновременно. Итак, я создал контейнерный класс под названием «пользователи». Этот класс имеет массив «пользовательских» объектов. Однако этот класс также имеет метод для загрузки данных для нескольких пользовательских объектов из базы данных (на основе таких критериев, как все платные пользователи), а затем для создания массива объектов с данными. Количество создаваемых объектов зависит от количества пользователей, возвращаемых из базы данных.

Ниже приведен пример кода для классов

class user
{
private $data;
function __construct ($arData=””)
{
$this->dbTable        ="user";
if(!is_array($ar))
{
if($ar!="")
{
$ar = $this->getDataFromDB($ar);
}
else
{
$ar = array();
}
}
$this->data = $ar;
}

function getDataFromDB($id_user){  … data base implementation … }
....
Other methods
....
}

class users // the container class
{
private $objUsers;
function __ construct(){
$this->objUsers = array();
}

function loadUsers($type){
$userDataArray = $this->getUsersFromDatabase($type);

foreach($useDataArray as $userData){
$this->objUsers[] = new user($userData);
}
}
function getUsersFromDatabase($userType) { …… database …… }
…… other methods …..
}

Меня беспокоит класс контейнера (контейнер не может быть правильным словом, чтобы сказать). Я хочу знать лучшую практику для создания этого типа контейнерного класса и то, что рекомендуется для этого. Кроме того, ясно видно, что этот контейнерный класс тесно связан с классом «пользователь» и не может тестироваться отдельно. Как я могу реализовать внедрение зависимости для такого класса?

0

Решение

Как я уже сказал, я не думаю, что это подходит для внедрения зависимости. И я бы не стал так настраивать просто ради того, чтобы сказать, что он использует внедрение зависимостей.

Основная причина, по которой он не подходит, заключается в том, что пользователь всегда является пользователем. Таким образом, у вас всегда есть конкретный договор между оберткой, пользователями и пользователем. Вы можете рассчитывать на пользователя, имеющего определенные методы. И у вас нет какого-то странного третьего класса, который вы добавляете в эти коллекции, это просто коллекция известного и четко определенного объекта.

Тем не менее, я бы пошел с более фабричной оболочкой стиля, где пользователь является простым из 2 классов. (обратите внимание, я не проверял ничего из этого, так что просто посмотрите на это как псевдокод)

class users {

public function createUser( array $data = []){

if( $data['id'] ){
$User = $this->getUser( $data['id'] );
if( $User )
return $User;
}
//depending what you want you could search on other things
//like the email, (unique)  and return the user.
//you could make this as complex, or as simple as you want
//it could simply create a new user, or check for an existing one first.

return new User($data); //dependency
}

public function getUser( $id ){
$stmt = $this->DB->prepare( "SELECT * FROM users WHERE id=:id" );
$stmt->FetchMode(PDO::FETCH_CLASS, 'User');
return $stmt->fetch(); //fetch right into the class
}

public function saveUser( User $User ){
//I just added this to show how you can type hint the class
// so that it only accepts Objects of the type User
}

}

class user{

protected $id;
protected $username;
protected $email;public function __construct(array $data = []){
foreach( $data as $field=>$value){
//this could be done better, with error checking etc.
//but I just wanted to show how you can use the setters
//dynamically when constructing with an array
//this is useful because we are not hard coding the schema of User in any files
//-note- PHP method calls are case insensitive.
$this->set{$field} = $value;
}
}

public function setId( $id ){ $this->id = $id; }

public function getId(){ return $this->id; }

public function setUsername( $username ){ $this->username = $username; }

public function getUsername(){ $this->username; }

public function setEmail( $email ){ $this->email = $email; }

public function getEmail(){ return $this->email; }
}

Тогда вы можете беспокоиться о внедрении зависимостей для таких вещей, как база данных. Это можно представить, если конструктор пользователей принимает объект PDO или базу данных. Как это

class Users{
protected $DB;

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

Класс Users не заботится об учетных данных БД или даже конкретном используемом вами драйвере БД. В некоторой степени он имеет некоторую связь с драйвером на основе синтаксиса SQL, который может быть специфичным для конкретной базы данных. Если мы хотим сделать это «более верной» формой внедрения зависимостей, мы должны использовать ORM, такой как Doctrine, или какой-нибудь конструктор запросов (вместо самого PDO). Тогда у нас будет еще один уровень абстракции между нашим кодом и базой данных.

1

Другие решения

Если вам нужен пользователь, чтобы иметь доступ к пользователям, и они не могут быть разделены, расширьте класс.

class users {

}

class user extends users {

}

Затем дочерний пользователь может получить доступ к свойствам родительских пользователей.

-2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector