我不确定这是否完全是错误的事情,所以我正在寻找一些建议。
我已经建立了一个数据库类,构造函数建立了一个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);