PHP OOP-将DB类注入另一个类的构造方法
我有一个连接数据库的PHP OOP-将DB类注入另一个类的构造方法,php,Php,我有一个连接数据库的类 <?php require_once('config.php'); class Database { function __construct(){ $this->connect(); } public function connect(){ $this->connection = mysqli_connect(SERVER, USERNAME, PASSWORD, DATABASE); } }
类
<?php
require_once('config.php');
class Database {
function __construct(){
$this->connect();
}
public function connect(){
$this->connection = mysqli_connect(SERVER, USERNAME, PASSWORD, DATABASE);
}
}
?>
但这不起作用,因为对于仍然在主类中的查询,我得到了一个错误,我打算稍后将它们移动到DB类中。但现在我得到了一个错误:
致命错误:未捕获错误:调用未定义的方法
/home/vagrant/Projects/MyProject/index.php中的数据库::query()
在线262
查询在主类中完成:
$result = $this->mysqli->query( "SELECT shops.*, shops.id AS shop,SUM(price)...
您正在尝试调用数据库
类上的query()
方法。虽然该类在其$connection
属性中包含mysqli
对象,但它不公开该mysqli
对象的query()
方法
给定当前的代码,您可以进一步深入对象结构,直接在mysqli
上调用query()
,但这很麻烦
// Call the query() method directly on the connection
$result = $this->mysqli->connection->query( "SELECT shops.*, shops.id AS shop,SUM(price)...
我不喜欢这种方法,因为它要求您的类比它们可能应该知道的更多地了解数据库的内部工作。它把他们结合得太紧密了
或者,您可以在数据库
类中创建一个query()
方法,将mysqli
对象的必要功能封装在其中
class Database {
function __construct(){
$this->connect();
}
public function connect(){
$this->connection = mysqli_connect(SERVER, USERNAME, PASSWORD, DATABASE);
}
// Expose a query() method that calles the inner mysqli's query
public function query($sql) {
return $this->connection->query($sql);
}
}
这将允许您打包更多功能,例如在一个方法调用中查询和获取所有结果行:
class Database {
//....
// A more featured query() that returns the
// rows as an array
public function query($sql) {
$result = $this->connection->query($sql);
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
// Return an array of all the rows fetched from the query
return $rows;
}
}
如果您这样做,您应该能够像最初尝试的那样调用$this->mysqli->query(“…”)
,或者使用简单版本获取结果资源,之后您必须自己获取代码,或者在更具特色的版本中获取关联结果行数组
但是,创建这些类型的数据库包装类可能会很快变得笨拙。仔细考虑希望向应用程序中的其他类公开mysqli
对象的哪些方面。在数据库
类中包装每个mysqli
方法不是一个好主意。此时,数据库
类的实用性大大降低,您也可以直接传入一个mysqli
对象。如果您没有主动向mysqli
添加功能,那么创建另一个封装它的类就没有什么意义了
关于var$mysqli的注释代码>。。。这是一个旧的不推荐使用的类属性语法。var
关键字是PHP4的残余,现在不鼓励使用它。事实上,它已经从最近的PHP版本中删除。相反,您应该通过PHP5+语法声明它:
// Declare as a public property
public $mysqli;
// Or better, as a private (or protected) property so it cannot
// be accessed outside the Main class' own methods
private $mysqli;
在你的问题标题中,你提到了注射。您的类现在没有这样做,但是最好提前实例化数据库,并将其注入需要它的类构造函数中
class Main{
public $mysqli;
// Pass a database as a constructor param
public function __construct($database){
$this->mysqli = $database;
}
然后将其实例化为:
$db = new Database();
// Pass the $db to the other classes
$main = new Main($db);
重要的是,这将防止您为实例化的Main
的每个对象以及以相同方式构造的任何其他类打开单独的数据库连接。这样做可以快速使用服务器可用的MySQL连接。以$this->mysqli->query()的形式访问查询函数;我们在这里看不到query
的用法,因此我们无法帮助您在数据库类中调用query()
必须为$this->connection->query()
,除非您编写一个query()
方法将其直接包装到Database
类中。请将代码张贴在您试图调用query()
@MichaelBerkowski的位置。我已将查询添加到question@Leff好的,我充实了一个答案。@Leff这有意义吗?非常可靠的答案!我会使用private$mysqli
而不是public
,因此您不能从对象外部访问属性以强制松耦合+1尽管@ʰᵈˑ我同意,但不想引入太多的概念或太多地改变OP的原始方法。我再补充一点。
$db = new Database();
// Pass the $db to the other classes
$main = new Main($db);