Memcache results and while loop - php

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

Related

php nested do-while loop terminating after first iteration

I'm using nested do-while loop for accessing two json result, unfortunately the loop terminates after the first iteration where it returns outer-loop json result and not executing the inner-loop. Please find the function where am using nested do-while loop:
public function data_report($fromdate, $todate)
{
$lp = new log_report();
$mysqli = new mysqli("172.16.10.102", "aventador", "RND#ISO-3306", "eTrans");
if ($mysqli->connect_errno)
{
$response["success"] = 0;
}
if (!$mysqli->multi_query("call sp_Android_Online_Dashboard('$fromdate','$todate')"))
{
$response["success"] = 0;
}
else {
//1st Iteration
do {
if ($res = $mysqli->store_result())
{
$response["values"] = array();
while ($row = $res->fetch_assoc())
{
$i=1;
$value = array();
$value["location_name"] = $row["location_name"];
$value["location_id"] = $row["location_id"];
$value["Totfiles"] = $row["Totfiles"];
$arr = explode(":", $row["file_minutes"], 2);
$value["file_minutes"] = $arr[0];
$value["Total_Lines"] = round($row["Total_Lines"], 0, PHP_ROUND_HALF_UP);
array_push($response["values"], $value);
echo $i++;
}
if (!$mysqli->multi_query("call sp_get_Android_Online_minutes_Chart('$fromdate','$todate')"))
{
$response["success"] = 0;
}
//2nd Iteration
do {
if ($res = $mysqli->store_result())
{
$response["Chart_data"] = array();
while ($row = $res->fetch_assoc())
{
$j=5;
$value = array();
$value["File_Day"] = $row["FileDay"];
$value["File_Minutes"] = $row["Tot_minutes"];
array_push($response["Chart_data"], $value);
}
$response["success"] = 1;
echo json_encode($response, JSON_NUMERIC_CHECK);
$res->free();
}
echo $j++;
} while($mysqli->more_results() && $mysqli->next_result());
}
echo json_encode($response, JSON_NUMERIC_CHECK);
} while($mysqli->more_results() && $mysqli->next_result());
}
}
Please help me out in solving this issue, thanks in advance!!

return array in function

I want to translate each words in array:
$myarray = array("hi","bro");
So I wrote a translate function like this:
function translate($word) {
foreach ( $word as $key_translate ) {
$array = array();
$sql = mysql_query("SELECT * FROM `translate` WHERE name = '".$key_translate."' ");
if ( mysql_num_rows($sql) == 1 ) {
$row = mysql_fetch_array($sql);
$name = $row['fa_name'];
return $name;
//retuen array($name);
}
else {
return $key_translate;
//return array($key_translate);
}
}
}
And using this to show translated array:
print_r (translate($myarray));
But it's not returning array, it's just showing first key as string.
How can I return array in function?
Don't return inside the loop, that exits the whole function immediately and just returns that one element. Accumulate the results in an array, and return that.
function translate($word) {
$result = array();
foreach ( $word as $key_translate ) {
$sql = mysql_query("SELECT fa_name FROM `translate` WHERE name = '".$key_translate."' ");
if ( mysql_num_rows($sql) == 1 ) {
$row = mysql_fetch_array($sql);
$result[] = $row['fa_name'];
}
else {
$result[] = $key_translate;
}
}
return $result;
}
Also, there's no reason to use SELECT * if you're only interested in fa_name.
Try this:
function translate($word) {
foreach ($word as $key => $translate) {
$sql = mysql_query("SELECT * FROM `translate` WHERE name = '" . $translate . "' ");
if (mysql_num_rows($sql) == 1) {
$row = mysql_fetch_array($sql);
$word[$key] = $row['fa_name'];
}
}
return $word;
}

how to loop through a multi dimensional associative array the correct way

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);
}

Fetch array, multidimensional?

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)

How can I simplify this PHP?

I have the following model functions with PHP.
I know I am repeating myself.
Is there anyway I can simplify this code?
function getTopMenus(){
$data[0] = 'root';
$this->db->where('parentid',0);
$Q = $this->db->get('menus');
if ($Q->num_rows() > 0){
foreach ($Q->result_array() as $row){
$data[$row['id']] = $row['name'];
}
}
$Q->free_result();
return $data;
}
function getheadMenus(){
$this->db->where('parentid',0);
$Q = $this->db->get('menus');
if ($Q->num_rows() > 0){
foreach ($Q->result_array() as $row){
$data[] = $row;
}
}
$Q->free_result();
return $data;
}
function getrootMenus(){
$this->db->where('parentid',0);
$Q = $this->db->get('menus');
if ($Q->num_rows() > 0){
foreach ($Q->result_array() as $row){
$data[$row['id']] = $row['name'];
}
}
$Q->free_result();
return $data;
}
I can see one simplification you might try, using pass-by-reference to factor things out into a function:
function prepareMenu(&$data) {
$this->db->where('parentid',0);
$Q = $this->db->get('menus');
if ($Q->num_rows() > 0){
foreach ($Q->result_array() as $row){
$data[$row['id']] = $row['name'];
}
}
$Q->free_result();
}
function getTopMenus() {
$data[0] = 'root';
prepareMenus($data);
return $data;
}
function getRootMenus() {
prepareMenus($data);
return $data;
}
There's also the possibility of using pass-by-reference and variable functions to factor out the part in the middle. May reduce duplication, but may or may not be considered 'simplifying'.
EDIT Here's what I mean. This code is untested.
function getMenus(&$data, $appendFunc) {
$this->db->where('parentid',0);
$Q = $this->db->get('menus');
if ($Q->num_rows() > 0){
foreach ($Q->result_array() as $row){
$appendFunc(&$data, $row);
}
}
$Q->free_result();
}
function appendTopMenu(&$data, $row) {
$data[$row['id']] = $row['name'];
}
function appendHeadMenu(&$data, $row) {
$data[] = $row;
}
function getTopMenus() {
$data[0] = 'root';
getMenus($data, "appendTopMenu");
return $data;
}
function getheadMenus() {
getMenus($data, "appendHeadMenu");
return $data;
}
function getrootMenus() {
getMenus($data, "appendTopMenu");
return $data;
}
Why not pass parameters into your function and place them in the 'where' and 'get' methods?
I don't know what your db and query classes look like, but i'd start improving these in the first place. Add "array fetch" and "hash fetch" functions to the query class:
class Query ...
function as_array() {
$data = array();
if($this->num_rows() > 0)
foreach ($this->result_array() as $row)
$data[] = $row;
$this->free_result();
return $data;
}
function as_hash($key = 'id') {
$data = array();
if($this->num_rows() > 0)
foreach ($this->result_array() as $row)
$data[$row[$key]] = $row;
$this->free_result();
return $data;
}
Make 'db->where()' return itself
class DB
function where(...) {
stuff
return $this;
Once you have this, your client functions become trivial:
function getTopMenus() {
$data = $this->db->where('parentid',0)->get('menus')->as_hash();
$data[0] = 'root';
return $data;
}
function getheadMenus() {
return $this->db->where('parentid',0)->get('menus')->as_array();
}
function getrootMenus() {
return $this->db->where('parentid',0)->get('menus')->as_hash();
}

Categories