dabro
12-17-2007, 08:01 AM
I am having a very strange issue with looping through a record set using a while loop and mysql_fetch_assoc. Basically, only first row of the data set is returned, after which nothing else happens as if it has got to the end of the data set (which I know is false, because the query generates more results).
I have run the query using an SQL browser with the database and it returns the expected results (3 in this case to be exact). This is also corroburated by the fact that I can call mysql_fetch_rows on the resource and correctly get the 3 rows returned as the number of results. However, mysql_fetch_assoc in PHP is only ever giving me the first result as described above.
This is the MYSQL class I am using:
<?php
class Mysql extends Database {
private $connection;
private $schema;
private $query;
private $reservedFunctions;
public function __construct($id) {
$this->reservedFunctions = array(
"now()"
);
$config = Configuration::getInstance();
if(isset($id)) {
$host = $config->configuration->database->$id->host;
$port = $config->configuration->database->$id->port;
$user = $config->configuration->database->$id->user;
$password = $config->configuration->database->$id->password;
$db = $config->configuration->database->$id->schema;
} else {
$host = $config->configuration->database->default->host;
$port = $config->configuration->database->default->port;
$user = $config->configuration->database->default->user;
$password = $config->configuration->database->default->password;
$db = $config->configuration->database->default->schema;
}
if(!$this->connection = mysql_connect($host.":".$port, $user, $password)) exit(mysql_error());
if(!$this->schema = mysql_select_db($db, $this->connection)) exit(mysql_error());
}
public function delete($table, $where) {
if(!is_array($where)) throw new Exception("Where clauses needs to be an array");
$query = "DELETE FROM $table";
$query .= " WHERE ";
$query .= join(" AND ", $where);
if(!mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function fetchResults($ref) {
if(!isset($this->query[$ref])) throw new Exception("No query exists with reference #$ref");
return mysql_fetch_assoc($this->query[$ref]);
}
public function select($ref, $table, $fields = null, $where = null, $order = null, $limit = null, $debug = null) {
if(isset($this->query[$ref])) throw new Exception("A query using reference #$ref already exists");
$query = "SELECT ";
if(isset($fields)) {
if(!is_array($fields)) throw new Exception("Fields clauses need to be an array");
$query .= join(",", $fields);
} else {
$query .= "*";
}
$query .= " FROM ".$table;
if(isset($where)) {
if(!is_array($where)) throw new Exception("Where clauses needs to be an array");
$query .= " WHERE ";
$query .= join(" AND ", $where);
}
if(isset($order)) {
if(!is_array($order)) throw new Exception("Order clause needs to be an array");
$query .= " ORDER BY ";
$query .= join(",", $order);
}
if(isset($limit)) {
$query .= " LIMIT ".$limit;
}
if($debug) var_dump($query);
if(!$this->query[$ref] = mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function save($id = null, $table, $fields) {
if(is_null($id)) {
$this->insert($table, $fields);
} else {
$this->update($table, $fields, $id);
}
}
public function insert($table, $data) {
foreach($data as $field => $value) {
$fields[] = $field;
$values[] = in_array($value, $this->reservedFunctions) ? $value : "\"".Functions::escape($value)."\"";
}
$query = "INSERT INTO $table (".join(", ", $fields).") ";
$query .= "VALUES (".join(",", $values).")";
if(!mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function update($table, $values, $conditions) {
$query = "UPDATE $table SET ";
foreach($values as $field => $value) {
if(!eregi("^[0-9]+$", $field)) {
if(in_array($value, $this->reservedFunctions)) {
$val = $value;
} else {
$val = "\"".Functions::escape($value)."\"";
}
$query .= "$field = $val, ";
}
}
$query = substr($query, 0, -2);
if(is_array($conditions)) $query .= " WHERE ".join(" AND ", $conditions);
if(!mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function query($ref, $query) {
if(!$this->query[$ref] = mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function countResults($ref) {
if(!isset($this->query[$ref])) throw new Exception("No query exists with reference #$ref");
return mysql_num_rows($this->query[$ref]);
}
public function freeResults($ref = null) {
if(isset($ref)) {
$this->query[$ref] = null;
} else {
foreach($this->query as $ref) {
$this->query[$ref] = null;
}
}
}
public function getLastId() {
return mysql_insert_id($this->connection);
}
}
?>
And here is the class using the while loop:
<?php
class PermissionCollection extends Collection {
public function __construct(&$parentRef, $protected = null) {
$this->initialise($parentRef, $protected);
$this->singleton = "Permission";
$this->table = "permissions";
$this->callBackVar = "permissions";
}
public function loadPermissionsForAdmin($userID) {
$db = Database::getInstance();
$db->freeResults(0);
$db->select(0, "administratorpermissions", null, array("administratorid = $userID"), array("id ASC"));
var_dump("Rows: ".$db->countResults(0)."<br>");
while ($row = $db->fetchResults(0)) {
$this->addObject($row["permissionid"]);$count++;
}var_dump("Loops: $count");
}
public function checkPermission($code) {
if ($this->getObjectCount() > 0) {
foreach ($this->objects as $permission) {
if ($permission->getField("code") == $code) return true;
}
}
return false;
}
}
?>
I have left my debugging var_dumps in, so its easier to see the affected section. The first dump, returning the rows, comes out as 3 (correct). But the secound dump (loop iterations) comes out as 1 (incorrect).
I have been up all night with this one and am completely stumped. Hopefully, I have missed somethign really obvious through being tired and someone will point it out straight away.
If you need any more information, just let me know.
I have run the query using an SQL browser with the database and it returns the expected results (3 in this case to be exact). This is also corroburated by the fact that I can call mysql_fetch_rows on the resource and correctly get the 3 rows returned as the number of results. However, mysql_fetch_assoc in PHP is only ever giving me the first result as described above.
This is the MYSQL class I am using:
<?php
class Mysql extends Database {
private $connection;
private $schema;
private $query;
private $reservedFunctions;
public function __construct($id) {
$this->reservedFunctions = array(
"now()"
);
$config = Configuration::getInstance();
if(isset($id)) {
$host = $config->configuration->database->$id->host;
$port = $config->configuration->database->$id->port;
$user = $config->configuration->database->$id->user;
$password = $config->configuration->database->$id->password;
$db = $config->configuration->database->$id->schema;
} else {
$host = $config->configuration->database->default->host;
$port = $config->configuration->database->default->port;
$user = $config->configuration->database->default->user;
$password = $config->configuration->database->default->password;
$db = $config->configuration->database->default->schema;
}
if(!$this->connection = mysql_connect($host.":".$port, $user, $password)) exit(mysql_error());
if(!$this->schema = mysql_select_db($db, $this->connection)) exit(mysql_error());
}
public function delete($table, $where) {
if(!is_array($where)) throw new Exception("Where clauses needs to be an array");
$query = "DELETE FROM $table";
$query .= " WHERE ";
$query .= join(" AND ", $where);
if(!mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function fetchResults($ref) {
if(!isset($this->query[$ref])) throw new Exception("No query exists with reference #$ref");
return mysql_fetch_assoc($this->query[$ref]);
}
public function select($ref, $table, $fields = null, $where = null, $order = null, $limit = null, $debug = null) {
if(isset($this->query[$ref])) throw new Exception("A query using reference #$ref already exists");
$query = "SELECT ";
if(isset($fields)) {
if(!is_array($fields)) throw new Exception("Fields clauses need to be an array");
$query .= join(",", $fields);
} else {
$query .= "*";
}
$query .= " FROM ".$table;
if(isset($where)) {
if(!is_array($where)) throw new Exception("Where clauses needs to be an array");
$query .= " WHERE ";
$query .= join(" AND ", $where);
}
if(isset($order)) {
if(!is_array($order)) throw new Exception("Order clause needs to be an array");
$query .= " ORDER BY ";
$query .= join(",", $order);
}
if(isset($limit)) {
$query .= " LIMIT ".$limit;
}
if($debug) var_dump($query);
if(!$this->query[$ref] = mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function save($id = null, $table, $fields) {
if(is_null($id)) {
$this->insert($table, $fields);
} else {
$this->update($table, $fields, $id);
}
}
public function insert($table, $data) {
foreach($data as $field => $value) {
$fields[] = $field;
$values[] = in_array($value, $this->reservedFunctions) ? $value : "\"".Functions::escape($value)."\"";
}
$query = "INSERT INTO $table (".join(", ", $fields).") ";
$query .= "VALUES (".join(",", $values).")";
if(!mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function update($table, $values, $conditions) {
$query = "UPDATE $table SET ";
foreach($values as $field => $value) {
if(!eregi("^[0-9]+$", $field)) {
if(in_array($value, $this->reservedFunctions)) {
$val = $value;
} else {
$val = "\"".Functions::escape($value)."\"";
}
$query .= "$field = $val, ";
}
}
$query = substr($query, 0, -2);
if(is_array($conditions)) $query .= " WHERE ".join(" AND ", $conditions);
if(!mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function query($ref, $query) {
if(!$this->query[$ref] = mysql_query($query, $this->connection)) throw new Exception(mysql_error());
return true;
}
public function countResults($ref) {
if(!isset($this->query[$ref])) throw new Exception("No query exists with reference #$ref");
return mysql_num_rows($this->query[$ref]);
}
public function freeResults($ref = null) {
if(isset($ref)) {
$this->query[$ref] = null;
} else {
foreach($this->query as $ref) {
$this->query[$ref] = null;
}
}
}
public function getLastId() {
return mysql_insert_id($this->connection);
}
}
?>
And here is the class using the while loop:
<?php
class PermissionCollection extends Collection {
public function __construct(&$parentRef, $protected = null) {
$this->initialise($parentRef, $protected);
$this->singleton = "Permission";
$this->table = "permissions";
$this->callBackVar = "permissions";
}
public function loadPermissionsForAdmin($userID) {
$db = Database::getInstance();
$db->freeResults(0);
$db->select(0, "administratorpermissions", null, array("administratorid = $userID"), array("id ASC"));
var_dump("Rows: ".$db->countResults(0)."<br>");
while ($row = $db->fetchResults(0)) {
$this->addObject($row["permissionid"]);$count++;
}var_dump("Loops: $count");
}
public function checkPermission($code) {
if ($this->getObjectCount() > 0) {
foreach ($this->objects as $permission) {
if ($permission->getField("code") == $code) return true;
}
}
return false;
}
}
?>
I have left my debugging var_dumps in, so its easier to see the affected section. The first dump, returning the rows, comes out as 3 (correct). But the secound dump (loop iterations) comes out as 1 (incorrect).
I have been up all night with this one and am completely stumped. Hopefully, I have missed somethign really obvious through being tired and someone will point it out straight away.
If you need any more information, just let me know.