通常应该将连接传递给用户,所以您的用户类应该在其构造函数中接受一个数据库类型对象,然后使用该数据库对象执行对数据库的查询。这样,您的数据访问逻辑与业务逻辑分离。这被称为组合,与您所说的继承相反。
如果您真的想要技术上更好的实现,最好有一个仅包含公共变量的用户对象,然后使用“服务”来实现您的业务逻辑。
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
的特殊情况?我不确定其他人怎么看,但我会有点生气。我认为你需要了解里氏替换原则。
至于解决你的"有人告诉我全局变量很糟糕"问题,这里有两个视频供您观看:
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)的扩展;即使这样做可以满足你的需求,但这并不是一种合适的面向对象编程实践。
根据对象的定义,它相当简单。它是数据和对该数据执行的操作的封装,因此,如果我们仅考虑理论观点,它将使我们处于愉悦的环境。
我的建议是创建一个抽象数据访问类,其中包含通用的基本CRUD操作和使用PDO、ADO或其他数据库抽象库的简单查询执行。现在,将此类用作大多数模型类(如用户)的父类。
现在,抽象数据访问类提供了基本的CRUD,您可以编写特定于用户对象的行为,例如通过使用抽象父类的简单查询接口获取用户的所有帖子。
这种方法将在耦合功能方面带来更多的模块化,以及更高的可读性和可重用性。
对于特定情况,我认为这种方法没有任何问题。您可以使用它来简单地将用户的DB凭据封装在一个对象中,以便他们不必在每个使用DB对象的地方都指定它们。
$db = new UserDB();
会比较好一些
$db = new StandarDB($username, $password, $default_db);