我有一个用 PHP 编写的 MySQL 单例类。其代码如下:
class Database {
private $_result = NULL;
private $_link = NULL;
private $_config = array();
private static $_instance = NULL;
// Return singleton instance of MySQL class
public static function getInstance(array $config = array()) {
if (self::$_instance === NULL) {
self::$_instance = new self($config);
}
return self::$_instance;
}
// Private constructor
private function __construct(array $config) {
if (count($config) < 4) {
throw new Exception('Invalid number of connection parameters');
}
$this->_config = $config;
}
// Prevent cloning class instance
private function __clone() {}
// Connect to MySQL
private function connect() {
// Connect only once
static $connected = FALSE;
if ($connected === FALSE) {
list($host, $user, $password, $database) = $this->_config;
if ((!$this->_link = mysqli_connect($host, $user, $password, $database))) {
throw new Exception('Error connecting to MySQL : ' . mysqli_connect_error());
}
$connected = TRUE;
unset($host, $user, $password, $database);
}
}
// Perform query
public function query($query) {
if (is_string($query) and !empty($query)) {
$this->connect();
if ((!$this->_result = mysqli_query($this->_link, $query))) {
throw new Exception('Error performing query ' . $query . ' Message : ' . mysqli_error($this->_link));
}
}
}
// Fetch row from result set
public function fetch() {
if ((!$row = mysqli_fetch_object($this->_result))) {
mysqli_free_result($this->_result);
return FALSE;
}
return $row;
}
// Get insertion ID
public function getInsertID() {
if ($this->_link !== NUlL) {
return mysqli_insert_id($this->_link);
}
return NULL;
}
// Count rows in result set
public function countRows() {
if ($this->_result !== NULL) {
return mysqli_num_rows($this->_result);
}
return 0;
}
// Close the database connection
function __destruct() {
is_resource($this->_link) AND mysqli_close($this->_link);
}
}
我还有这个递归函数,它必须返回完整的类别树(SQL 表及其内容可以在 here 中找到):
function getCategories($parent = 0) {
$html = '<ul>';
$query = "SELECT * FROM `categories` WHERE `category_parent` = '$parent'";
$database->query($query);
while($row = $database->fetch()) {
$current_id = $row->category_id;
$html .= '<li>' . $row->category_name;
$has_sub = 0;
$query = "SELECT `category_parent` FROM `categories` WHERE `category_parent` = '$current_id'";
$database->query($query);
$has_sub = $database->countRows();
if ($has_sub > 0) {
$html .= getCategories($current_id);
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
现在的问题是该函数仅返回 3 个类别,而不是完整的树。我使用普通 MySQL 函数(mysql_query()、mysql_fetch_object() 等)重写了该函数,它返回了正确的结果。
所以我的结论是该类有问题。请注意,我在大多数项目中都使用了此类,但从未遇到过此问题。
知道什么吗?
谢谢。
编辑:尝试使其返回关联数组
function getCategories($parent = 0) {
global $database;
$categories = array();
$query = "SELECT * FROM `categories` WHERE `category_parent` = '$parent'";
$database->query($query);
while($row = $database->fetch()) {
$categories[] = array('id' => $row->category_id, 'name' => $row->category_name);
}
for ($i = 0; $i < count($categories); $i++) {
$categories[$i]['id']['children'] = getCategories($categories[$i]['id']);
}
return $categories;
}
上面的代码返回以下数组,但不太好:
Array
(
[0] => Array
(
[id] => 1
[name] => Categoria 1
[children] => Array
(
[0] => Array
(
[id] => 4
[name] => Categoria 1.1
[children] => Array
(
[0] => Array
(
[id] => 7
[name] => Categoria 1.1.2
[children] => Array
(
)
)
)
)
[1] => Array
(
[id] => 5
[name] => Categoria 1.2
[children] => Array
(
)
)
[2] => Array
(
[id] => 6
[name] => Categoria 1.3
[children] => Array
(
)
)
)
)
[1] => Array
(
[id] => 2
[name] => Categoria 2
[children] => Array
(
)
)
[2] => Array
(
[id] => 3
[name] => Categoria 3
[children] => Array
(
)
)
)
最佳答案
您看到的问题是您在第一个查询上运行了其他查询。因此,在递归第一个分支之后,函数会失败,因为它返回到原始 which
循环,并发现它已经位于第一个分支的结果行的末尾(3 级递归) .
一种快速解决方法是使用两个循环而不是一个循环来重写函数。您还可以通过减少必须进行的数据库调用次数来优化该函数。
您的第一个查询没问题。但在 while
循环中,只需获取适当的 id
和 name
元素并将它们存储在数组中。然后重新循环刚刚创建的数组以进行递归。此外,您可以通过不运行“检查”查询来消除多个查询。只需递归 - 如果 id
:name
数组中没有元素 - 返回一个空字符串。
编辑:示例(未经测试)
function getCategories($parent = 0) {
$categories = array();
$html = "<ul>";
$query = "SELECT * FROM `categories` WHERE `category_parent` = '$parent'";
$database->query($query);
while($row = $database->fetch()) {
$categories[$row->category_id] = $row->category_name;
}
foreach($categories as $cid=>$category) {
$html .= "<li>{$row->category_name}";
$inner = getCategories($cid);
if($inner != "<ul></ul>")
$html .= $inner;
$html .= "</li>"
}
$html .= "</ul>";
return $html;
}
关于php - MySQL 单例类与递归函数冲突(PHP),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3337840/