您的代码示例中有一些与您在问题中要求的内容相关的问题,因此我想突出显示它们。
最明显的问题是您没有传递数据库连接对象。相反,您将其包装到类型dtb
中,以便稍后在其他类型中展开,例如在您的user
:
function login() {
...
$results = mysqli_query($this->db->connection,"select * from user");
^--^--- unwrapping
...
相反,user
类型应该只有连接。它不需要知道dtb
包装:
function login() {
...
$results = mysqli_query($this->connection, "select * from user");
^--- one thing, not one thing and another
...
除此之外,您没有使用mysqli
扩展的 OO 接口。您的示例代码很好地证明了这不必要地使您的代码复杂化。让我们用 mysqli 的方式来做:
function login() {
...
$results = $this->connection->query("select * from user");
...
如您所见,您可以在不使用指定mysqli_*
函数的情况下使用连接,而只需使用query
对象的方法即可。
所以现在这行代码就很本地化了。该$connection
对象需要进入user
, 用于您迄今为止使用的非 OO 后台全局变量。但是在面向对象编程中,类的代码中不应该使用全局变量。那是因为程序代码中的全局变量是$this
类中的变量。$this
应该包含类中的方法所需的一切——如果没有提供方法参数。
所以你的多样化类是基于数据库连接的。你想在每个班级都有它。一个类在它的构造方法中被初始化。在那里,您将所有内容作为初始化类所需的参数传递。让我们以user
示例类为例:
class User
{
private $connection;
public function __construct(Mysqli $connection) {
$this->connection = $connection;
}
public function login() {
$resultSet = $this->connection->query("SELECT * FROM user;");
}
}
正如你所看到的,User
在它的构造方法中初始化__construct
了Mysqli
连接。然后可以使用该连接,$this->connection
因为它已分配给该私有变量。
您现在可以放心,一旦类被实例化,连接将保持不变。如果您需要同时打开与另一个数据库的连接,这也很有用。无论您需要创建多少个 Mysqli 连接,您的代码都将继续工作。
所以现在来使用:
$connection = new Mysqli('localhost','root','','new5');
$user = new User($connection);
$user->login();
就是这样。当然,在创建 Mysqli 连接对象的位置和创建用户的位置之间可能存在一些代码,但您需要做的就是传递连接。
这不会停在这里,尽管我已经接近这里的博客文章。您可能想要做的甚至是消除每个类中连接细节的负担,而是从负责重复数据库交互代码的基类扩展,以便在更高级别的类中您可以更专注于数据库细节上的工作和更少。有很多不同的方法可以做到这一点。从基类扩展只是其中之一。一个非常简单的例子:
class Database
{
private $connection;
public function __construct(Mysqli $connection) {
$this->connection = $connection;
}
protected function query($sql) {
return $this->connection->query($sql);
}
}
class User extends Database
{
$resultSet = $this->query("SELECT * FROM user;");
}
例如,如果您有一组公共类,只是其属性名称不同,则公共基类可以包含实现该目标的代码,而从它扩展的类只需要为此指定参数。
但正如所写,有许多不同的方式将类映射到数据库连接。有时您根本不想映射它们。做最适合你的事情,玩一点。如果您始终在构造函数中进行初始化并阻止使用全局变量(以及也是全局变量的静态类变量),那么您将保持灵活性并且实际上可以玩得更好。
请记住:每个人都在用水做饭,这背后没有魔法。