具有对象数组作为类属性

时间:2017-10-29 02:22:45

标签: php arrays oop dependency-injection containers

我是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 …..
}

我关注的是容器类(容器可能不是正确的说法)。我想知道创建这种类型的容器类的最佳实践,以及对此的建议。此外,很明显这个容器类与“用户”类紧密耦合,不能单独测试。如何为这样的类实现依赖注入?

2 个答案:

答案 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 {

}

然后,子用户可以访问父用户属性。