我有一个Database
类用于连接数据库。
<?php
require_once('config.php');
class Database {
function __construct(){
$this->connect();
}
public function connect(){
$this->connection = mysqli_connect(SERVER, USERNAME, PASSWORD, DATABASE);
}
}
?>
我需要使用数据库连接的主类:
include 'includes/database.php';
class Main{
var $mysqli;
public function __construct(){
$this->mysqli = new Database();
}
但是这不起作用,因为我仍然在主类中的查询出错,我打算稍后将它们移到DB类。但现在我收到了一个错误:
致命错误:未捕获错误:调用未定义的方法 /home/vagrant/Projects/MyProject/index.php中的Database :: query() 在第262行
查询在Main类中完成:
$result = $this->mysqli->query( "SELECT shops.*, shops.id AS shop,SUM(price)...
答案 0 :(得分:1)
您正尝试在query()
课程上调用Database
方法。虽然该类在其mysqli
属性中包含$connection
对象,但它不公开该query()
对象的mysqli
方法。
根据您当前的代码,您可以深入钻取对象结构,直接在query()
上调用mysqli
,但这很麻烦。
// Call the query() method directly on the connection
$result = $this->mysqli->connection->query( "SELECT shops.*, shops.id AS shop,SUM(price)...
我不喜欢这种方法,因为它要求你的课程更多地了解Database
课程的内部工作方式,而不是他们可能应该做的。它把它们紧密地联系起来。
作为替代方法,您可以在query()
类中创建一个Database
方法,该方法包含其中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
课程中包含每个Database
方法的路径并不是一个好主意。此时,Database
类的效用大大降低,您也可以直接传入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;
在你的问题标题中,你提到了注射。你的班级现在没有这样做,但提前实例化Database
并将一个注入到需要它的类构造函数中是个好主意。
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连接。