我是php中OOP编程的新手,并试图理解并实现我的MVC项目中的依赖注入功能。在下面我将解释一个非常简单的功能示例,我正在努力应用依赖注入。实际的应用程序比这复杂得多,但是,这应该足以证明我遇到的问题。
我创建了一个名为“user”的模型,负责管理单个用户。类处理的数据(关于用户的数据)也保存在数据库表中。 “user”类具有从数据库表加载和保存/更新数据的方法。可以使用从数据库加载的数据(通过使用用户ID)或从提供给构造函数的数组加载来启动用户类。
该项目一次处理多个用户。所以,我创建了一个名为“users”的容器类。该类具有一组“用户”对象。但是,此类还具有从数据库加载多个用户对象的数据的方法(基于所有付费用户等标准),然后使用数据创建对象数组。创建的对象数取决于从数据库返回的用户数。
以下是类
的示例代码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 :(得分:1)
正如我所说,我认为这不适合依赖注入。而且我不会这样设置它只是为了说它使用依赖注入。
它不适合的主要原因是用户始终是用户。因此,您始终在包装器,用户和用户之间签订具体合同。您可以指望用户拥有某些方法。而且你没有添加到这些集合中的一些奇怪的第3课,它只是一个已知且定义明确的对象的集合。
那就是说,我会选择一个更工厂风格的包装器,其中User更简单。 (注意,我没有测试任何这个,所以只要像psudo代码那样看一下)
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或Database对象来表示。喜欢这个
class Users{
protected $DB;
public function __construct( $DB ){
$this->DB = $DB;
}
}
Users类并不关心数据库凭据,甚至不关心您使用的特定数据库驱动程序。在某种程度上,它确实与基于SQL语法的驱动程序有一些耦合,这可能是特定于特定数据库的。如果我们想让它成为一个更真实的"依赖注入的形式我们应该使用像Doctrine这样的ORM,或者某种Query构建器(而不是PDO本身)。然后我们在代码和数据库之间会有另一层抽象。
答案 1 :(得分:-2)
如果您需要用户访问用户并且无法将其分开,请扩展该类。
class users {
}
class user extends users {
}
然后,子用户可以访问父用户属性。