PHP用户类是否应该扩展数据库类?


Should a PHP user class extend a database class?

我不确定这是否完全是错误的事情,所以我正在寻找一些建议。

我已经建立了一个数据库类,构造函数建立了一个PDO连接到MySQL数据库。

我一直在研究单例和全局变量,但似乎总是有人建议反对/或。

我正在尝试扩展数据库类的用户类,因此我可以调用PDO函数/方法,但维护单独的用户类代码。这么做很蠢吗?

通常应该将连接传递给用户,这样用户类就可以将数据库类型对象放入其构造函数中,然后使用该数据库对象对数据库执行查询。这样,您的数据访问逻辑与业务逻辑保持分离。这叫做组合,与你所说的继承相反。

如果你真的想要技术,最好有一个除了公共变量之外什么都没有的user对象,然后你将使用一个"服务"来实现你的业务逻辑。

class UserService implements IUserService
{
    private $_db;
    function __construct(IDb $db) {
        $this->_db = db;
    }
    function GetAllUsers() {
        $users = Array();
        $result = $this->_db->Query("select * from user")
        foreach($result as $user) {
            //Would resolve this into your user domain object here
            users[] = $user;
        }
        return users;
    }
}

那么,问问自己User是否是Database的特例。我不知道别人会怎么看,但我会觉得被冒犯了。我认为你需要的是阅读Liskov替换原理

为了解决你的"别人告诉我全局变量不好"问题,这里有两个你应该看的视频:

  • 整洁代码演讲-不要寻找东西!
  • Clean Code Talks - Global State and singleton

OOP中类扩展背后的思想是使子类与父类相关。例如,一个学校可能有一个Person类,其扩展类为Faculty和Students。这两个子类都是人,所以它们扩展Person类是有意义的。但是User不是一种数据库类型,所以如果你把它做成扩展,有些人可能会不高兴。

个人而言,我会将数据库对象作为参数发送给构造函数中的User类,并简单地将该对象分配给类属性。例如:

class User
{
    protected $db;
    function __construct($username, $password, $db)
    {
        //some code...
        $this->db = $db;
    }
}
另外,尽管有些人可能会对您大喊大叫,但您可以使用global关键字在全局作用域中继承一个变量,以便在您的方法中使用。缺点是你必须在每个需要它的方法中声明它是全局的,或者你可以这样做:
class User
{
    protected $db;
    function __construct($username, $password)
    {
        global $db;
        //some code...
        $this->db = $db;
    }
}

但在回答你的问题,不,我不认为你应该让用户数据库的扩展;尽管它可以做您需要的事情,但它不是一个合适的OOP实践。

根据对象的定义,这非常简单。它是数据的封装和对数据执行的操作,所以如果我们只考虑理论的观点,它会把我们带到一个愉快的环境。

我的建议是创建一个抽象的数据访问类,使用通用的基本crud操作和一个简单的查询执行,使用PDO, ADO或其他一些数据库抽象库。现在使用这个类作为你的大多数模型类的父类,比如User。

现在,基本的CRUD由抽象数据访问类提供,您可以编写特定于用户对象的行为,例如通过使用抽象父类的简单查询接口获取用户的所有帖子。

这种方法将在耦合功能方面带来更多的模块化,以及更好的可读性和可重用性。

我看不出它在特定情况下有什么问题。您可以将它用于简单的事情,例如将用户的DB凭据包装在对象中,这样他们就不必在使用DB对象的任何地方指定它们。

$db = new UserDB();

会比

好一点
$db = new StandarDB($username, $password, $default_db);