【问题标题】:Should a PHP user class extend a database class?PHP 用户类应该扩展数据库类吗?
【发布时间】:2011-12-11 06:42:24
【问题描述】:

我不确定这是否是完全错误的做法,所以我正在寻求一些建议。

我已经设置了一个数据库类,其构造函数建立了与 MySQL 数据库的PDO 连接。

我一直在研究singletons 和全局变量,但似乎总有人建议反对非此即彼。

我正在试验一个扩展数据库类的用户类,因此我可以调用 PDO 函数/方法,但维护单独的用户类代码。这是一件愚蠢的事情吗?

【问题讨论】:

  • 你的用户功能是什么?他们应该怎么做?
  • 添加新用户,更新用户详细信息等...
  • 如果您将用户数据存储在数据库中 - 我认为从 DB 继承您的用户类是正确的方法
  • ORM/DAO/DataMapper/ActiveRecord/TableGateway differences? 的可能重复项 - 它不完全适合,但基本上它包含您想要搜索的术语,尤其是 ActiveRecord。您提供的信息无法回答在您的应用程序中使用该模式是好主意还是坏主意。一般来说,它有一些问题。实际上,它有效。

标签: php database class pdo


【解决方案1】:

您通常应该将连接传递给您的用户,因此您的用户类会将数据库类型对象带入其构造函数,然后使用该数据库对象对数据库执行查询。这样,您的数据访问逻辑与您的业务逻辑保持分离。这称为组合,与您所说的相反,即继承。

如果您真的想成为技术人员,最好有一个只包含公共变量的用户对象,然后您将使用“服务”来实现您的业务逻辑。

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;
    }
}

【讨论】:

  • 我认为这就是我现在正在做的,但不确定这是否是最好的方法。我目前创建了一个用户对象并将数据库连接详细信息传递给它。然后构造调用父构造并建立连接 - 这就是你的意思吗?
  • 对不起 - 再次阅读您的帖子,因为我误解了。因此,考虑到你所说的,如果我继续创建其他类会发生什么 - 如果它们都连接到数据库,那不是很理想吗???
  • 您可以将 db 对象的相同(已经构建的)实例传递给任何需要连接的人。当然是在一个请求中。
  • 添加了轻量级代码示例。用于抽象的接口,但不是概念所必需的。
  • 绝对是要走的路。每个类应该有一个单独的职责,如果它们需要一起工作,应该使用依赖注入进行组合。
【解决方案2】:

好吧,问问自己User 是否是Database 的特例。我不确定其他人如何看待它,但我会有点被冒犯。我认为您需要阅读Liskov substitution principle

至于解决您的“人们告诉我全局变量不好”问题,您应该观看以下两个视频:

【讨论】:

  • 两个非常好的链接。我并不经常在网上听到/读到与那些视频一样合乎逻辑且呈现良好的东西。谢谢。
【解决方案3】:

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;
    }
}

但在回答你的问题时,不,我认为你不应该让 User 成为数据库的扩展;即使它可以满足您的需要,但这不是正确的 OOP 实践。

【讨论】:

  • 您好,感谢您的回复——我有点担心全局变量,因为很多人似乎都警告过它们。我采用上面的 Nathans 方法并将一个 db 对象传递给 User 构造函数。这似乎可以解决问题!
  • 我能问一下吗 - 在您的第一个代码示例中,我注意到您有 $username 和 $password 参数以及 $db 对象参数。为什么你有 $user/$pass ,因为当你创建数据库对象时肯定已经建立了连接?
  • 抱歉混淆了...构造函数中的 $username 和 $password 不是用于数据库的,而是 User 对象中用户的用户名和密码。我只是假设您将使用用户的用户名和密码实例化 User 对象以进行身份​​验证。
  • 哦,好吧 - 那么这让我想到了这个问题......你是否真的在你的用户类中有一个方法来注册/添加一个用户到数据库,因为显然没有用户名/提供创建用户对象的密码???
  • 用户类应该能够在没有来自数据库的信息的情况下被实例化。理想情况下,用户类将用于注册用户和匿名访客用户,在这种情况下,它将填充默认信息,例如访问者的 IP 等。然后是的,如果用户使用给定信息是匿名的,就会有一种方法来注册用户,只需要他们提供用户名、密码、电子邮件等。
【解决方案4】:

根据对象的定义,这很简单。它是数据的封装和对数据执行的操作,所以如果我们只考虑理论的观点,它会让我们处于愉快的环境中。

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

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

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

【讨论】:

  • 将不得不研究抽象类
【解决方案5】:

对于特定情况,我认为它没有任何问题。您可以将它用于简单的事情,例如将用户的数据库凭据包装在一个对象中,这样他们就不必在使用数据库对象的任何地方指定它们。

$db = new UserDB();

会比

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

【讨论】:

  • 不,真的不会。
猜你喜欢
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 2012-06-27
  • 2012-07-31
  • 2013-02-06
相关资源
最近更新 更多