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

6

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

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

我一直在研究单例模式和全局变量,但总有人建议不要使用其中之一。

我正在尝试使用继承数据库类的用户类,这样我就可以调用PDO函数/方法,但保持独立的用户类代码。这样做是愚蠢的吗?


你的用户函数是什么?他们应该做什么? - user973254
添加新用户,更新用户详细信息等。 - tommyd456
如果您将用户数据存储在数据库中,我认为从DB继承用户类是正确的方式。 - user973254
可能是[ORM/DAO/DataMapper/ActiveRecord/TableGateway differences?]的重复问题(https://dev59.com/qHA75IYBdhLWcg3wm6ex)-虽然不完全匹配,但基本上包含了您想要谷歌的术语,特别是ActiveRecord。从您提供的信息中无法回答在应用程序中使用该模式是好还是坏的想法。一般来说,它有一些问题。在实践中,它可以工作。 - Gordon
5个回答

4

通常应该将连接传递给用户,所以您的用户类应该在其构造函数中接受一个数据库类型对象,然后使用该数据库对象执行对数据库的查询。这样,您的数据访问逻辑与业务逻辑分离。这被称为组合,与您所说的继承相反。

如果您真的想要技术上更好的实现,最好有一个仅包含公共变量的用户对象,然后使用“服务”来实现您的业务逻辑。

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连接详细信息传递给它。构造函数然后调用父构造函数并建立连接 - 这是你的意思吗? - tommyd456
抱歉 - 我再次阅读了您的帖子,因为我误解了。那么,考虑到您所说的,如果我继续创建其他类 - 如果它们都连接到数据库,那不是很理想,对吗? - tommyd456
当然,在单个请求中,您将向任何需要连接的人传递相同(已构造)的db对象实例。 - nathan gonzalez
添加了轻量级代码示例。接口用于抽象,但对于概念并非必需。 - nathan gonzalez
绝对是正确的方法。每个类应该有单独的职责,并且如果它们需要一起工作,则应使用依赖注入进行组合。 - dqhendricks

4

两个非常好的链接。我很少在网上听/读到像那些视频一样逻辑清晰、表述得当的东西。谢谢。 - James

2
在面向对象编程中,类扩展的想法是使子类与父类相关联。例如,学校可能有一个Person类,其扩展类为Faculty和Students。这两个子类都是人,因此将它们扩展到Person类中是有意义的。但是,User不是Database的一种类型,因此如果将其作为扩展,有些人可能会感到不满。
个人认为,在构造函数中将数据库对象作为参数发送到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)作为数据库(Database)的扩展;即使这样做可以满足你的需求,但这并不是一种合适的面向对象编程实践。


抱歉造成困惑... 构造函数中的 $username 和 $password 不是用于数据库,而是用于 User 对象中用户的用户名和密码。我只是假设您将使用用户的用户名和密码实例化 User 对象进行身份验证。 - imkingdavid
用户类应该能够在没有数据库信息的情况下被实例化。理想情况下,用户类将用于注册用户和匿名访客用户,此时它将填充默认信息,如访问者的IP等。然后,如果用户是匿名的,就会有一种方法来使用给定的信息注册用户,只需要提供用户名、密码、电子邮件等即可。 - imkingdavid
这是因为类是一个对象,类的属性被用作描述该对象的属性(例如用户名,密码,IP,是否登录等),而其方法是用户可以执行或可以对用户执行的操作。用户可以注册,用户可以登录,用户可以进行身份验证等。 - imkingdavid
是的,我同意 - 但我已经决定(你可能会反对)将$username/$password传递给登录方法而不是构造函数。这对我来说似乎更有意义。 - tommyd456
这也可以运作(事实上,在我最近的脚本中就是这样做的)。我认为两种方式都不一定对或错-- 事实上,前者在等待创建用户对象直到有用户/密码信息方面可能更加困难-- 这真的只是因人而异,取决于个人偏好和哪种方法最适合你。 - imkingdavid
显示剩余3条评论

0

根据对象的定义,它相当简单。它是数据和对该数据执行的操作的封装,因此,如果我们仅考虑理论观点,它将使我们处于愉悦的环境。

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

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

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


需要研究抽象类。 - tommyd456

-5

对于特定情况,我认为这种方法没有任何问题。您可以使用它来简单地将用户的DB凭据封装在一个对象中,以便他们不必在每个使用DB对象的地方都指定它们。

$db = new UserDB();

会比较好一些

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

2
不,实际上不会。 - Madara's Ghost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接