I'm using this database MySQLi wrapper:
Class dbWrapper {
protected $_mysqli;
protected $_debug;
public function __construct($host, $username, $password, $database, $debug) {
$this->_mysqli = new mysqli($host, $username, $password, $database);
$this->_mysqli->set_charset("utf8");
$this->_debug = (bool) $debug;
if (mysqli_connect_errno()) {
if ($this->_debug) {
echo mysqli_connect_error();
debug_print_backtrace();
}
return false;
}
return true;
}
public function q($query) {
if ($query = $this->_mysqli->prepare($query)) {
if (func_num_args() > 1) {
$x = func_get_args();
$args = array_merge(array(func_get_arg(1)),
array_slice($x, 2));
$args_ref = array();
foreach($args as $k => &$arg) {
$args_ref[$k] = &$arg;
}
call_user_func_array(array($query, 'bind_param'), $args_ref);
}
$query->execute();
if ($query->errno) {
if ($this->_debug) {
echo mysqli_error($this->_mysqli);
debug_print_backtrace();
}
return false;
}
if ($query->affected_rows > -1) {
return $query->affected_rows;
}
$params = array();
$meta = $query->result_metadata();
while ($field = $meta->fetch_field()) {
$params[] = &$row[$field->name];
}
call_user_func_array(array($query, 'bind_result'), $params);
$result = array();
while ($query->fetch()) {
$r = array();
foreach ($row as $key => $val) {
$r[$key] = $val;
}
$result[] = $r;
}
$query->close();
return $result;
} else {
if ($this->_debug) {
echo $this->_mysqli->error;
debug_print_backtrace();
}
return false;
}
}
public function handle() {
return $this->_mysqli;
}
}
But when I make a query, for example SELECT This FROM Database, and I want to display the result, I have to echo $result[0]['This']. Why that? Why not $result['This']? I changed this:
$result = array();
while ($query->fetch()) {
$r = array();
foreach ($row as $key => $val) {
$r[$key] = $val;
}
$result[] = $r;
}
$query->close();
return $result;
to this:
$result = array();
while ($query->fetch()) {
foreach ($row as $key => $val) {
$result[$key] = $val;
}
$result[] = $r;
}
$query->close();
return $result;
But why do all the wrappers I see, return a multidimensional array?
Hope you understand me. Thank you!
The reason they return multidimensional arrays is because you can have more than one result.
So:
$data[0]['name'] is the first returned records name.
$data[1]['name'] is the second returned records name.
You can create a fetchRow() function which will always just return the first record when you only expect one row
return $data[0]
OR
a fetchOne()
return $data[0]['name']
When you only expect one field
Usually, when you're gathering results from a DB query, you have multiple rows.
--------------
- 1 --- This -
- 2 --- That -
--------------
So you get a multi-dimensional array in order to handle all the rows in one object.
...Is that not the case here?
EDIT:
$result = array();
while ($query->fetch()) {
$r = array();
foreach ($row as $key => $val) {
$r[$key] = $val;
}
$result[] = $r;
}
$query->close();
return $result;
in the above code, you are assigning each individual row to an index in the $results array. In order to access them, you need to provide $results[ROW_NUMBER][KEY_NAME];
Does that make sense?
I'm going to take a shot and say maybe try $query->fetch_row() instead of $query->fetch() (just a guess)
Related
I wrote this function for caching queries:
function get_cached($query, $type = 1) {
$key = md5(strtolower($query));
$cached = $memcache->get($key);
if($cached) {
$res = unserialize($cached);
} else {
$r = mysql_query($query);
if($mode == 1) {
$res = mysql_fetch_object($r);
} else {
$res = mysql_fetch_array($r);
}
$memcache->store($key, serialize($res));
}
return $res;
}
And it kinda works, i can cache simple queries. But i have problem with queries that operate within loops.
I really can't understand how to get around this, and "port" this to use my get_cached() function first.
$ref = mysql_query("query");
while($res = mysql_fetch_object($ref)) {
//do something with results
}
How i can do it through cache?
You cannot store the mysql result object but you can fetch all rows into an array and cache the array. like
function get_cached($query, $type = 1) {
$key = md5(strtolower($query) . $type);
$cached = $memcache->get($key);
if($cached) {
return unserialize($cached);
} else {
$r = mysql_query($query);
$data = array();
if($mode == 1) {
foreach($row = mysql_fetch_object($r)) {
$data[] = $row;
}
} else {
foreach($row = mysql_fetch_array($r)) {
$data[] = $row;
}
}
$memcache->store($key, serialize($data));
}
return $data;
}
don't forget to store the type of your functions as cache key too, otherwise you fetch a results set with type==1 and in return you get the elements as array
This is the error I'm getting:
Allowed memory size of 1258291200 bytes exhausted (tried to allocate 4294967296 bytes)
on this line: call_user_func_array(array($query, 'bind_result'), $params);
Funnily enough, I've used this exact script dozens of time without issue. So I think it might be something in my server/db set up but can't think of anything.
Here's the full function:
public function q($query) {
if ($query = $this->_mysqli->prepare($query)) {
if (func_num_args() > 1) {
$x = func_get_args();
$args = array_merge(array(func_get_arg(1)),
array_slice($x, 2));
$args_ref = array();
foreach($args as $k => &$arg) {
$args_ref[$k] = &$arg;
}
call_user_func_array(array($query, 'bind_param'), $args_ref);
}
$query->execute();
if ($query->errno) {
if ($this->_debug) {
echo mysqli_error($this->_mysqli);
debug_print_backtrace();
}
return false;
}
if ($query->affected_rows > -1) {
return $query->affected_rows;
}
$params = array();
$meta = $query->result_metadata();
while ($field = $meta->fetch_field()) {
$params[] = &$row[$field->name];
}
call_user_func_array(array($query, 'bind_result'), $params);
$result = array();
while ($query->fetch()) {
$r = array();
foreach ($row as $key => $val) {
$r[$key] = $val;
}
$result[] = $r;
}
$query->close();
foreach($result as $key=>$resultField){
$result[$key] = (object) $resultField;
}
return $result;
} else {
if ($this->_debug) {
echo $this->_mysqli->error;
debug_print_backtrace();
}
return false;
}
}
Please do not tell me to increase the memory limit. I'm looking for a fix to the problem, not the symptom.
Turns out I was using longtext unnecessarily and using up all my memory. Switching to mediumtext solved the issue.
i am at the point in my script where i want to insert data into my database after looping through an associative array.
the code works so far but since i am new to programming i wish to know if there is a more efficient alternative way of doing what i am doing, since i will be adding more elseif's when my array grows, and also the fact that i am querying my database after every iteration.
foreach($database as $key=>$value) {
foreach($value as $field => $cell){
if ($field =='itemid') {
echo "the item id is $cell";
$col1 = $cell ;
}
elseif ($field =='title') {
echo "the title is $cell";
$col2 = $cell;
}
elseif ($field =='starttime') {
echo "the start time is $cell";
$col3 = $cell;
}
}
$query = "INSERT INTO cordless_drill(itemid,title,starttime) VALUES ('$col1','$col2','$col3')";
mysqli_query($dbc,$query);
}
// here is a code snippet
// $db = new MyDbClass();
// $db->insert->('cordless_drill', $cell); // where $cell is holding key/value pairs
public function insert($table, $obj) {
return $this->query("INSERT INTO ".$table.$this->obj2KeyValue($obj));
}
private function obj2KeyValue($obj) {
$i = count($obj);
$k = ""; $v = "";
$init = false;
$sql = " SET ";
while (list($k, $v) = each($obj)) {
if ($v != "") {
$v = $this->mysqli->real_escape_string($v);
if ($init) $sql .= ", ";
else $init = true;
$sql .= $k.'="'.$v.'"';
}
}
return $sql;
}
public function query($q) {
if ($this->debug) {
$logFile = "sql_query.log";
$handle = fopen($logFile, "a+");
$data = $q."\n";
fwrite($handle, $data);
fclose($handle);
}
return $this->mysqli->query($q);
}
I wasn't so clear in my first question, so i deleted it and here is a reformulation;
I have those arrays:
$open = array(array("FAI1","34"),array("FAI2","34"),array("FAI3","34"));
$click = array(array("FAI2","52"),array("FAI1","68"),array("FAI3","99"));
$unsubscribe = array(array("FAI2","103"),array("FAI3","67"),array("FAI1","102"));
$def_sent = array(array("FAI1","34",24),array("FAI2","34",23),array("FAI3","34",27));
$SB = array(array("FAI2","103"),array("FAI3","67"),array("FAI1","102"));
$HB = array(array("FAI2","103"),array("FAI3","67"),array("FAI1","102"));
I searched for a function to merge them and get a result like this:
$result = array(array("FAI1",34,68,102,34,24,102,102)
,array("FAI2","34",23.....),
array("FAI3","34",27....));
and to do this, i used the function, in the php online documentation, and this is the function
function array_merge_recursive() {
$arrays = func_get_args();
$base = array_shift($arrays);
foreach ($arrays as $array) {
reset($base);
while (list($key, $value) = #each($array)) {
if (is_array($value) && #is_array($base[$key])) {
$base[$key] = array_merge_recursive($base[$key], $value);
} else {
$base[$key] = $value;
}
}
}
return $base;
}
But instead of getting the result above i got this:
FAI1|34
FAI2|34
FAI3|34
FAI2|52
FAI1|68
FAI3|99
...
So i need some help to reformulate this function to get the expected result.
Try this function:
function array_merge_rec() {
$arrays = func_get_args();
$result = array();
foreach ($arrays as $arg) {
if (is_array($arg)) {
foreach ($arg as $item) {
if (!isset($result[$item[0]])) {
$result[$item[0]] = $item;
} else {
$result[$item[0]][] = $item[1];
}
}
} else {
echo "$arg skippend because it isn't array\n";
}
}
return array_values($result);
}
Does it help?
I have a PHP class that is meant to get a mysqli query, make a multidimensional array, and currently just echo the whole array. It is this code:
include("connect.php");
class database
{
public $motto;
public $motto_array = array();
public $rating;
public $rating_array = array();
public $category;
public $score;
private $mysqli;
public $counter_array = array();
public $multi_dim_values = array();
public $multi_dim_category = array();
function setMysqli($mysqli)
{
$this->mysqli = $mysqli;
}
function setCategory($category)
{
$this->category = $category;
}
function query_category()
{
if ($stmt = $this->mysqli->prepare("SELECT motto, score FROM mottos WHERE category=? ORDER BY score DESC"))
{
$stmt->bind_param("s", $this->category);
$stmt->execute();
$stmt->bind_result($motto, $ranking);
while ( $stmt->fetch() ) {
$this->motto_array[] = $motto;
$this->rating_array[] = $ranking;
}
$stmt->close();
}
}
function multi_dim_array()
{
$multi_dim_values = array($this->motto_array, $this->rating_array);
$counter_array = range(0,count($this->motto_array)-1);
foreach($counter_array as $index => $key) {
$foreach_array = array();
foreach($multi_dim_values as $value) {
$foreach_array[] = $value[$index];
}
$multi_dim_category[$key] = $foreach_array;
}
return $multi_dim_category;
}
}
$class = new database;
$class->SetMysqli($mysqli);
$class->SetCategory("person");
$class->query_category();
print_r($class->multi_dim_array);
print_r($class->multi_dim_category);
connect.php has the database connection information for the mysqli.
I am learning OOP, so I did this in procedural, and it works fine, with this code:
include("connect.php");
function category($mysqli, $cat)
{
if ($stmt = $mysqli->prepare("SELECT motto, score FROM mottos WHERE category=? ORDER BY score DESC"))
{
$stmt->bind_param("s", $cat);
$stmt->execute();
while($stmt->fetch())
{
printf ("[%s (%s) in %s] \n", $motto, $ranking, $category);
$array .= compact("motto", "category", "ranking");
}
print_r($array);*/
$a = array();
$b = array();
$c = array();
$stmt->bind_result($motto, $ranking);
while ( $stmt->fetch() ) {
$a[] = $motto;
$b[] = $ranking;
}
$result = array();
$values = array($a, $b);
$c = range(0,count($a)-1);
foreach($c as $index => $key) {
$t = array();
foreach($values as $value) {
$t[] = $value[$index];
}
$result[$key] = $t;
}
return $result;
$stmt->close();
}
}
$cat = "person";
$array_one = category($mysqli, $cat);
print_r($array_one);
This prints the multidimensional array just like I want it to.
What am I doing wrong in the OOP code?
Thank you.
Your code:
print_r($class->multi_dim_array);
You forgot the (), so you're not invoking the method. You're accessing a (non-existent) property. Try this:
print_r($class->multi_dim_array());