I have a MySQL singleton class written in PHP. Its code is listed below:
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);
}
}
I also have this recursive function which must returns a full category tree (the SQL table and its content can be found 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;
}
Now, the problem is that the function returns only 3 categories, not the full tree. I rewrote the function using plain MySQL functions (mysql_query(), mysql_fetch_object() etc.) and it returns the right result.
So my conclusion in that there's something wrong with that class. Note that I've been using this class in most of my projects, but never had this issue.
Any idea what?
Thanks.
EDIT: Trying to make it to return an associative array
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;
}
The code above returns the following array, but is not quite ok:
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
(
)
)
)