jsTree Multiple Tree MySQL/PHP implementation - Nested-sets - php

I have implemented jsTree on my site with a php/MySQL back-end for tree storage and retrieval. I used the php/MySQL demo that came with the jsTree download for the basic infrastructure and then modified to my needs.
I have modified so that multiple trees can be stored in the same database, and added a new column of "owner_id" that stores the userid of the person that created that particular tree.
The php code that creates a new branch or moves a branch is not working correctly as it is not taking into account that there are multiple trees within the database.
jsTree uses the nested set model, and the script is adjusting the left and right values of all the trees in the database instead of just the one that has had a new branch added. This is slowly corrupting the entire database.
The following code shows the function/s that does the adjusting, could someone please try and amend the code for me so it uses the "owner_id" field to only make the changes to a particular tree?
function _create($parent, $position) {
return $this->_move(0, $parent, $position);
}
and then...
function _move($id, $ref_id, $position = 0, $is_copy = false) {
$hbhbhbh = fSession::get('nodes_allowed[nodes_access]');
if ($hbhbhbh == "0" || $hbhbhbh == "2" || $hbhbhbh == "3") {
if((int)$ref_id === 0 || (int)$id === 1) { return false; }
$sql = array(); // Queries executed at the end
$node = $this->_get_node_ifuueuwyhddd($id); // Node data
$nchildren = $this->_get_children($id); // Node children
$ref_node = $this->_get_node_ifuueuwyhddd($ref_id); // Ref node data
$rchildren = $this->_get_children($ref_id);// Ref node children
$ndif = 2;
$node_ids = array(-1);
if($node !== false) {
$node_ids = array_keys($this->_get_children($id, true));
// TODO: should be !$is_copy && , but if copied to self - screws some right indexes
if(in_array($ref_id, $node_ids)) return false;
$ndif = $node[$this->fields["right"]] - $node[$this->fields["left"]] + 1;
}
if($position >= count($rchildren)) {
$position = count($rchildren);
}
// Not creating or copying - old parent is cleaned
if($node !== false && $is_copy == false) {
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " .
"WHERE " .
"`".$this->fields["parent_id"]."` = ".$node[$this->fields["parent_id"]]." AND " .
"`".$this->fields["position"]."` > ".$node[$this->fields["position"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$ndif." " .
"WHERE `".$this->fields["left"]."` > ".$node[$this->fields["right"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$ndif." " .
"WHERE " .
"`".$this->fields["right"]."` > ".$node[$this->fields["left"]]." AND " .
"`".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ";
}
// Preparing new parent
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` + 1 " .
"WHERE " .
"`".$this->fields["parent_id"]."` = ".$ref_id." AND " .
"`".$this->fields["position"]."` >= ".$position." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ref_ind = $ref_id === 0 ? (int)$rchildren[count($rchildren) - 1][$this->fields["right"]] + 1 : (int)$ref_node[$this->fields["right"]];
$ref_ind = max($ref_ind, 1);
$self = ($node !== false && !$is_copy && (int)$node[$this->fields["parent_id"]] == $ref_id && $position > $node[$this->fields["position"]]) ? 1 : 0;
foreach($rchildren as $k => $v) {
if($v[$this->fields["position"]] - $self == $position) {
$ref_ind = (int)$v[$this->fields["left"]];
break;
}
}
if($node !== false && !$is_copy && $node[$this->fields["left"]] < $ref_ind) {
$ref_ind -= $ndif;
}
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["left"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["right"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ldif = $ref_id == 0 ? 0 : $ref_node[$this->fields["level"]] + 1;
$idif = $ref_ind;
if($node !== false) {
$ldif = $node[$this->fields["level"]] - ($ref_node[$this->fields["level"]] + 1);
$idif = $node[$this->fields["left"]] - $ref_ind;
if($is_copy) {
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."`" .
") " .
"SELECT " .
"".$ref_id.", " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["right"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["level"]."` - (".$ldif.") " .
"FROM `".$this->table."` " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") " .
"ORDER BY `".$this->fields["level"]."` ASC";
}
else {
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["parent_id"]."` = ".$ref_id.", " .
"`".$this->fields["position"]."` = ".$position." " .
"WHERE " .
"`".$this->fields["id"]."` = ".$id;
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["left"]."` = `".$this->fields["left"]."` - (".$idif."), " .
"`".$this->fields["right"]."` = `".$this->fields["right"]."` - (".$idif."), " .
"`".$this->fields["level"]."` = `".$this->fields["level"]."` - (".$ldif.") " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") ";
}
}
else {
$ewre = fSession::get('user[user_id]');
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["owner"]."`, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."` " .
") " .
"VALUES (" .
$ewre.", " .
$ref_id.", " .
$position.", " .
$idif.", " .
($idif + 1).", " .
$ldif.
")";
}
foreach($sql as $q) { $this->db->query($q); }
$ind = $this->db->insert_id();
if($is_copy) $this->_fix_copy($ind, $position);
return $node === false || $is_copy ? $ind : true;
}
}
Any help really appreciated.
Thanks

For anyone else this might help, here is my code after the changes to I made to make creating / moving nodes only apply to the particular tree in question.
Adding the owner_id in the where clause did in fact fix the issue. I needed to add it to only certain queries:
function _move($id, $ref_id, $position = 0, $is_copy = false) {
$hbhbhbh = fSession::get('nodes_allowed[nodes_access]');
if ($hbhbhbh == "0" || $hbhbhbh == "2" || $hbhbhbh == "3") {
if((int)$ref_id === 0 || (int)$id === 1) { return false; }
$sql = array(); // Queries executed at the end
$node = $this->_get_node_ifuueuwyhddd($id); // Node data
$nchildren = $this->_get_children($id); // Node children
$ref_node = $this->_get_node_ifuueuwyhddd($ref_id); // Ref node data
$rchildren = $this->_get_children($ref_id);// Ref node children
$ndif = 2;
$node_ids = array(-1);
if($node !== false) {
$node_ids = array_keys($this->_get_children($id, true));
// TODO: should be !$is_copy && , but if copied to self - screws some right indexes
if(in_array($ref_id, $node_ids)) return false;
$ndif = $node[$this->fields["right"]] - $node[$this->fields["left"]] + 1;
}
if($position >= count($rchildren)) {
$position = count($rchildren);
}
// Not creating or copying - old parent is cleaned
if($node !== false && $is_copy == false) {
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " .
"WHERE " .
"`".$this->fields["owner"]."` = ".(int) $node[$this->fields["owner"]]." AND " .
"`".$this->fields["parent_id"]."` = ".$node[$this->fields["parent_id"]]." AND " .
"`".$this->fields["position"]."` > ".$node[$this->fields["position"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$ndif." " .
"WHERE `".$this->fields["left"]."` > ".$node[$this->fields["right"]]." AND " .
"`".$this->fields["owner"]."` = ".(int) $node[$this->fields["owner"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$ndif." " .
"WHERE " .
"`".$this->fields["owner"]."` = ".(int) $node[$this->fields["owner"]]." AND " .
"`".$this->fields["right"]."` > ".$node[$this->fields["left"]]." AND " .
"`".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ";
}
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` + 1 " .
"WHERE " .
"`".$this->fields["parent_id"]."` = ".$ref_id." AND " .
"`".$this->fields["position"]."` >= ".$position." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ref_ind = $ref_id === 0 ? (int)$rchildren[count($rchildren) - 1][$this->fields["right"]] + 1 : (int)$ref_node[$this->fields["right"]];
$ref_ind = max($ref_ind, 1);
$self = ($node !== false && !$is_copy && (int)$node[$this->fields["parent_id"]] == $ref_id && $position > $node[$this->fields["position"]]) ? 1 : 0;
foreach($rchildren as $k => $v) {
if($v[$this->fields["position"]] - $self == $position) {
$ref_ind = (int)$v[$this->fields["left"]];
break;
}
}
if($node !== false && !$is_copy && $node[$this->fields["left"]] < $ref_ind) {
$ref_ind -= $ndif;
}
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["owner"]."` = ".(int) $ref_node[$this->fields["owner"]]." AND `".$this->fields["left"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["owner"]."` = ".(int) $ref_node[$this->fields["owner"]]." AND `".$this->fields["right"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ldif = $ref_id == 0 ? 0 : $ref_node[$this->fields["level"]] + 1;
$idif = $ref_ind;
if($node !== false) {
$ldif = $node[$this->fields["level"]] - ($ref_node[$this->fields["level"]] + 1);
$idif = $node[$this->fields["left"]] - $ref_ind;
if($is_copy) {
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."`" .
") " .
"SELECT " .
"".$ref_id.", " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["right"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["level"]."` - (".$ldif.") " .
"FROM `".$this->table."` " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") " .
"ORDER BY `".$this->fields["level"]."` ASC";
}
else {
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["parent_id"]."` = ".$ref_id.", " .
"`".$this->fields["position"]."` = ".$position." " .
"WHERE " .
"`".$this->fields["id"]."` = ".$id;
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["left"]."` = `".$this->fields["left"]."` - (".$idif."), " .
"`".$this->fields["right"]."` = `".$this->fields["right"]."` - (".$idif."), " .
"`".$this->fields["level"]."` = `".$this->fields["level"]."` - (".$ldif.") " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") ";
}
} else {
$ewre = fSession::get('user[user_id]');
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["owner"]."`, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."` " .
") " .
"VALUES (" .
$ewre.", " .
$ref_id.", " .
$position.", " .
$idif.", " .
($idif + 1).", " .
$ldif.
")";
}
foreach($sql as $q) { $this->db->query($q); }
$ind = $this->db->insert_id();
if($is_copy) $this->_fix_copy($ind, $position);
return $node === false || $is_copy ? $ind : true;
}
}
Hope it helps someone...

Related

Pass optional SQL to prepared statement

I try to inject some optional SQL to prepared statement with the parameter $and:
public function loadInfoAndStatus($property_id, $property_item_type_id, $and, $returnArray = false)
{
if (!isset($property_id) || empty($property_id)
|| !isset($property_item_type_id) || empty($property_item_type_id)
|| !isset($and) || empty($and)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? "
. $this->con->real_escape_string($and) // <--- here
. " ORDER BY pi.status "
. " DESC LIMIT 0,1";
$err = "";
if (!$stmt = $this->con->prepare($sql)) {
$err .= "Prepare failed: (" . $this->con->errno . ") " . $this->con->error;
}
...
But if I call the function e.g.
$row2 = Main::getModel("Property/Item")->loadInfoAndStatus(
$id
, $property_item_type_id
, " AND c.iso = 'DE' "
, true
);
Hint: $and can be one of:
" AND c.iso <> 'DE' AND c.european <> 1 "
" AND c.iso <> 'DE' AND c.european = 1 "
" AND c.iso = 'DE' "
Then I get "Prepare failed" but there is no error message.
Resulting SQL:
SELECT pi.status, pi.info, pi.property_item_id FROM property_item pi JOIN countries c ON c.country_id = pi.country_id WHERE pi.property_id = ? AND property_item_type_id = ? AND c.iso = \'DE\' ORDER BY pi.status DESC LIMIT 0,1
It works if I don't use real_escape_string
Do I have to create new functions for each new sql, or is there another way?
You have to list all possible variants in your function.
This is a toilsome task but you have to realize that's the only way.
public function loadInfoAndStatus($property_id, $property_item_type_id, $iso = null, $european = null, $returnArray = false)
{
if (empty($property_id) || empty($property_item_type_id)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
$parameters = [$property_id, $property_item_type_id];
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? ";
if ($iso) {
$sql .= " AND c.iso <> ? ";
$parameters[] = $iso;
}
if ($european === true) {
$sql .= " AND c.european == 1 ";
} elseif ($european === false) {
$sql .= " AND c.european <> 1 ";
}
$sql .= " ORDER BY pi.status ";
$sql .= " DESC LIMIT 0,1";
$stmt = $this->con->prepare($sql);
$stmt->bind_param(str_repeat("s", count($parameters)), ...$parameters);
$stmt->execute();
I also removed some cargo cult code from your method, in case you are interested why
Do you really need to check for both isset() and empty() at the same time?
PHP error reporting
I solved the problem by using a whitelist method:
public function loadInfoAndStatus($property_id, $property_item_type_id, $and = "", $returnArray = false)
{
if (empty($property_id) || empty($property_item_type_id) || empty($and)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
if (!$this->isSqlInWhitelist($and, array(
"AND c.iso = 'DE'"
,"AND c.iso <> 'DE' AND c.european = 1"
,"AND c.iso <> 'DE' AND c.european <> 1"
))) {
error_log(get_class() . " - " . __FUNCTION__ ." : sql is not in whitelist.");
return false;
}
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? "
. $and
. " ORDER BY pi.status "
. " DESC LIMIT 0,1";
$stmt = $this->con->prepare($sql);
...
...
protected function isSqlInWhitelist($sql, $whitelist)
{
if (!empty($sql)) {
if (!in_array(trim($sql), $whitelist)) { return false; }
}
return true;
}

PHP Performance issue with loops

I use PHP to execute SQL queries and then extract timesheet data for a bunch of users.
Earlier it ran decently fast but has now slowed down drastically due to increase in number of Users and Tasks.
I have used a number of while, for loops. Not sure what I can optimize as calculations are iterative.
Appreciate if someone could look at the code and suggest some options.
private function processGETUSERTIMEREPORTDATA(SimpleXMLElement $xml, DBHandler $dbh) {
$from = Utils::convertToDatetime($this->clientDateFormat, $xml->FROM);
$to = Utils::convertToDatetime($this->clientDateFormat, $xml->TO);
$usercode = stripslashes(html_entity_decode($xml->UNCODE));
$this->logger->LogDebug("User List: " . $usercode);
$userArr = json_decode($usercode, TRUE);
$tChgMode = $xml->TASKCHGMODE;
$tType = $xml->TASKTYPE;
$timeSheetCategory = $xml->TIMESHEETCAT;
$totalChgHrsArr = array();
$totalNonChgHrsArr = array();
$totalGenNonChgHrsArr = array();
$totalChgDaysArr = array();
$totalDaysALeaveArr = array();
$totalDaysSLeaveArr = array();
$totalDaysCLeaveArr = array();
$totalExpensesArr = array();
// Set timesheet category table
if ($timeSheetCategory == "ALL") {
$tablename = array("tblChargeHours", "tblNonChargeHours", "tblFieldDays",
"tblNonChargeDays", "tblExpensesSheet", "tblGeneralNonChargeHours");
} else if ($timeSheetCategory == "Chargeable Hours") {
$tablename = array("tblChargeHours");
} else if ($timeSheetCategory == "Non Chargeable Hours") {
$tablename = array("tblNonChargeHours");
} else if ($timeSheetCategory == "Chargeable Days") {
$tablename = array("tblFieldDays");
} else if ($timeSheetCategory == "Leaves") {
$tablename = array("tblNonChargeDays");
} else if ($timeSheetCategory == "Expenses") {
$tablename = array("tblExpensesSheet");
} else if ($timeSheetCategory == "General Non Chargeable Hours") {
$tablename = array("tblGeneralNonChargeHours");
}
$arrlength = count($tablename);
$userCount = count($userArr);
for ($i = 0; $i < $userCount; $i++) {
for ($x = 0; $x < $arrlength; $x++) {
// Leaves table
if ($tablename[$x] == "tblNonChargeDays") {
// Annual Leave
$daysSum = 0;
$query = "SELECT Mo, Tu, We, Th, Fr, Sa, Su from " . $tablename[$x] . " WHERE (WeekEnding BETWEEN '$from' AND '$to') AND (TaskCode='1') AND (NameCode='" . $userArr[$i] . "')";
$hoursRes = $dbh->executeQuery($query);
if ($dbh->getQueryStatus()) {
while ($timerow = mysqli_fetch_assoc($hoursRes)) {
$daysSum += ($timerow['Mo'] + $timerow['Tu'] + $timerow['We'] + $timerow['Th'] + $timerow['Fr'] + $timerow['Sa'] + $timerow['Su']);
}
$totalDaysALeaveArr[] = $daysSum;
} else {
$this->logger->LogError("Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
return ResponseGenerator::generateNegativeRepsonse($this->reqName, "Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
}
// Sick Leave
$daysSum = 0;
$query = "SELECT Mo, Tu, We, Th, Fr, Sa, Su from " . $tablename[$x] . " WHERE (WeekEnding BETWEEN '$from' AND '$to') AND (TaskCode='2') AND (NameCode='" . $userArr[$i] . "')";
$hoursRes = $dbh->executeQuery($query);
if ($dbh->getQueryStatus()) {
while ($timerow = mysqli_fetch_assoc($hoursRes)) {
$daysSum += ($timerow['Mo'] + $timerow['Tu'] + $timerow['We'] + $timerow['Th'] + $timerow['Fr'] + $timerow['Sa'] + $timerow['Su']);
}
$totalDaysSLeaveArr[] = $daysSum;
} else {
$this->logger->LogError("Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
return ResponseGenerator::generateNegativeRepsonse($this->reqName, "Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
}
// Compassionate Leave
$daysSum = 0;
$query = "SELECT Mo, Tu, We, Th, Fr, Sa, Su from " . $tablename[$x] . " WHERE (WeekEnding BETWEEN '$from' AND '$to') AND (TaskCode='3') AND (NameCode='" . $userArr[$i] . "')";
$hoursRes = $dbh->executeQuery($query);
if ($dbh->getQueryStatus()) {
while ($timerow = mysqli_fetch_assoc($hoursRes)) {
$daysSum += ($timerow['Mo'] + $timerow['Tu'] + $timerow['We'] + $timerow['Th'] + $timerow['Fr'] + $timerow['Sa'] + $timerow['Su']);
}
$totalDaysCLeaveArr[] = $daysSum;
} else {
$this->logger->LogError("Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
return ResponseGenerator::generateNegativeRepsonse($this->reqName, "Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
}
// GeneralNonChgHours Table
} else if ($tablename[$x] == "tblGeneralNonChargeHours") {
$hoursSum = 0;
$query = "SELECT Mo, Tu, We, Th, Fr, Sa, Su from " . $tablename[$x] . " WHERE (WeekEnding BETWEEN '$from' AND '$to') AND (NameCode='" . $userArr[$i] . "')";
$hoursRes = $dbh->executeQuery($query);
if ($dbh->getQueryStatus()) {
while ($timerow = mysqli_fetch_assoc($hoursRes)) {
$hoursSum += ($timerow['Mo'] + $timerow['Tu'] + $timerow['We'] + $timerow['Th'] + $timerow['Fr'] + $timerow['Sa'] + $timerow['Su']);
}
$totalGenNonChgHrsArr[] = $hoursSum;
} else {
$this->logger->LogError("Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
return ResponseGenerator::generateNegativeRepsonse($this->reqName, "Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
}
}
} // end-for-tablename
} // end-for-usercode
if ($tChgMode == "ALL") {
if ($tType == "ALL") {
// $tChgMode = ALL && $tType = ALL
$tquery = "SELECT TCode, TType FROM tblTasks WHERE (TCreatedDate BETWEEN '$from' AND '$to')";
} else {
// $tChgMode = ALL && $tType = Sel
$tquery = "SELECT TCode, TType FROM tblTasks WHERE (TCreatedDate BETWEEN '$from' AND '$to') AND (TType='" . $tType . "') ORDER BY TCode ASC";
}
} else {
if ($tType == "ALL") {
// $tChgMode = Sel && $tType = ALL
$tquery = "SELECT TCode, TType FROM tblTasks WHERE (TCreatedDate BETWEEN '$from' AND '$to') AND (TChargeMode='" . $tChgMode . "') ORDER BY TCode ASC";
} else {
// $tChgMode = Sel && $tType = Sel
$tquery = "SELECT TCode, TType FROM tblTasks WHERE (TCreatedDate BETWEEN '$from' AND '$to') AND (TChargeMode='" . $tChgMode . "') AND (TType='" . $tType . "') ORDER BY TCode ASC";
}
}
$result = $dbh->executeQuery($tquery);
$tqueryArr = array(); // Store the query results
while ($row = mysqli_fetch_assoc($result)) {
$tqueryArr[] = $row;
}
for ($i = 0; $i < $userCount; $i++) {
$totalExpenses = 0;
$totalChgHrs = 0;
$totalNonChgHrs = 0;
$totalChgDays = 0;
foreach ($tqueryArr as $row) {
for ($x = 0; $x < $arrlength; $x++) {
$tCode = $row['TCode'];
// Expenses Table
if ($tablename[$x] == "tblExpensesSheet") {
$query = "SELECT FinalAmount from " . $tablename[$x] . " WHERE (WeekEnding BETWEEN '$from' AND '$to') AND (TaskCode='" . $tCode . "') AND (NameCode='" . $userArr[$i] . "')";
// $this->logger->LogDebug($query);
$hoursRes = $dbh->executeQuery($query);
if ($dbh->getQueryStatus()) {
while ($exprow = mysqli_fetch_assoc($hoursRes)) {
$totalExpenses += $exprow['FinalAmount'];
}
} else {
$this->logger->LogError("Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
return ResponseGenerator::generateNegativeRepsonse($this->reqName, "Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
}
// Other Tables
} else {
$query = "SELECT Mo, Tu, We, Th, Fr, Sa, Su from " . $tablename[$x] . " WHERE (WeekEnding BETWEEN '$from' AND '$to') AND (TaskCode='" . $tCode . "') AND (NameCode='" . $userArr[$i] . "')";
$hoursRes = $dbh->executeQuery($query);
$totalHours = 0;
if ($dbh->getQueryStatus()) {
while ($timerow = mysqli_fetch_assoc($hoursRes)) {
$hoursSum = ($timerow['Mo'] + $timerow['Tu'] + $timerow['We'] + $timerow['Th'] + $timerow['Fr'] + $timerow['Sa'] + $timerow['Su']);
$totalHours += $hoursSum;
}
switch ($tablename[$x]) {
case "tblChargeHours":
$totalChgHrs += $totalHours;
break;
case "tblNonChargeHours":
$totalNonChgHrs += $totalHours;
break;
case "tblFieldDays":
$totalChgDays += $totalHours;
break;
default:
}
} else {
$this->logger->LogError("Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
return ResponseGenerator::generateNegativeRepsonse($this->reqName, "Unable to generate Timesheet report data. Q : " . $query . " E : " . $dbh->getQueryMessage());
}
}
} // end-for
} // end-while
$totalExpensesArr[] = $totalExpenses;
$totalChgHrsArr[] = $totalChgHrs;
$totalNonChgHrsArr[] = $totalNonChgHrs;
$totalChgDaysArr[] = $totalChgDays;
} // end-for-usercode
$xmlop = new SimpleXMLElement('<RESPONSE/>');
$xmlop->addChild("REQUESTNAME", $this->reqName);
$xmlop->addChild("REQUESTSTATUS", "SUCCESS");
$rowxml = $xmlop->addChild("ROW");
$rowxml->addChild("USERCODE", json_encode($userArr));
$rowxml->addChild("CHGHOURS", json_encode($totalChgHrsArr));
$rowxml->addChild("NONCHGHOURS", json_encode($totalNonChgHrsArr));
$rowxml->addChild("GENNONCHGHOURS", json_encode($totalGenNonChgHrsArr));
$rowxml->addChild("FIELDDAYS", json_encode($totalChgDaysArr));
$rowxml->addChild("ANNLEAVE", json_encode($totalDaysALeaveArr));
$rowxml->addChild("SICKLEAVE", json_encode($totalDaysSLeaveArr));
$rowxml->addChild("COMPLEAVE", json_encode($totalDaysCLeaveArr));
$rowxml->addChild("EXPENSES", json_encode($totalExpensesArr));
return $xmlop->asXML();
}
Apart from the complicated code, you will probably find that you have an indexing (or lack of) issue.
Find every field that is used in any of the WHERE clauses and create an index for it.
It's quite possible that if you have a growing database that is gradually getting slower, it could be an indexing problem.

Getting JSON error after filtering data but Page loads fine without filtering

I have a grid that loads fine until I try to apply a filter then i get the following error.
Fatal error: Uncaught Error: Call to a member function fetch_assoc() on bool in
// build the query.
$result = $conn->query($query) or die("SQL Error 1: " . mysqli_error());
$sql = "SELECT FOUND_ROWS() AS `found_rows`;";
$rows = $conn->query($sql);
$rows = mysqli_fetch_assoc($rows);
$total_rows = $rows['found_rows'];
$query = "SELECT SQL_CALC_FOUND_ROWS profile_pic_url, username, full_name, biography, edge_followed_by, edge_follow FROM owner ORDER BY edge_followed_by DESC LIMIT $start, $total_rows".$where." ";
}
}
$result = $conn->query($query) ;
$sql = "SELECT FOUND_ROWS() AS `found_rows`;";
$rows = $conn->query($sql);
$rows = mysqli_fetch_assoc($rows);
$total_rows = $rows['found_rows'];
$orders = null;
// get data and store in a json array
while($row = $result->fetch_assoc()) {
#kryptur - this is where $where is defined
// filter data.
if (isset($_GET['filterscount']))
{
$filterscount = $_GET['filterscount'];
if ($filterscount > 0)
{
$where = " WHERE (";
$tmpdatafield = "";
$tmpfilteroperator = "";
for ($i=0; $i < $filterscount; $i++)
{
// get the filter's value.
$filtervalue = $_GET["filtervalue" . $i];
// get the filter's condition.
$filtercondition = $_GET["filtercondition" . $i];
// get the filter's column.
$filterdatafield = $_GET["filterdatafield" . $i];
// get the filter's operator.
$filteroperator = $_GET["filteroperator" . $i];
if ($tmpdatafield == "")
{
$tmpdatafield = $filterdatafield;
}
else if ($tmpdatafield <> $filterdatafield)
{
$where .= ")AND(";
}
else if ($tmpdatafield == $filterdatafield)
{
if ($tmpfilteroperator == 0)
{
$where .= " AND ";
}
else $where .= " OR ";
}
// build the "WHERE" clause depending on the filter's condition, value and datafield.
switch($filtercondition)
{
case "CONTAINS":
$where .= " " . $filterdatafield . " LIKE '%" . $filtervalue ."%'";
break;
case "DOES_NOT_CONTAIN":
$where .= " " . $filterdatafield . " NOT LIKE '%" . $filtervalue ."%'";
break;
case "GREATER_THAN":
$where .= " " . $filterdatafield . " > '" . $filtervalue ."'";
break;
case "LESS_THAN":
$where .= " " . $filterdatafield . " < '" . $filtervalue ."'";
break;
case "GREATER_THAN_OR_EQUAL":
$where .= " " . $filterdatafield . " >= '" . $filtervalue ."'";
break;
case "LESS_THAN_OR_EQUAL":
$where .= " " . $filterdatafield . " <= '" . $filtervalue ."'";
break;
}
if ($i == $filterscount - 1)
{
$where .= ")";
}
$tmpfilteroperator = $filteroperator;
$tmpdatafield = $filterdatafield;
}

Passing ID value from one table to another from drop down selection

What am I missing?
I have a drop down with values. I think everything is working fine, except when I post the results to another table I can't seem to get the gameID from the first table to post, it just goes through as blank. Am I missing an association with the team and the gameID?
Query to get data for drop down:
$sql = "select s.*, (DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR) > gameTimeEastern or DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR) > '" . $cutoffDateTime . "') as expired ";
$sql .= "from " . DB_PREFIX . "schedule s ";
$sql .= "inner join " . DB_PREFIX . "teams ht on s.homeID = ht.teamID ";
$sql .= "inner join " . DB_PREFIX . "teams vt on s.visitorID = vt.teamID ";
$sql .= "where s.weekNum = " . $week . " ";
$sql .= "order by s.gameTimeEastern, s.gameID";
//echo $sql;
$query = $mysqli->query($sql) or die($mysqli->error);
if ($query->num_rows > 0) {
$i = 0;
while ($row = $query->fetch_assoc()) {
$sGameID = (int)$row['gameID'];
$homeTeam = new team($row['homeID']);
$visitorTeam = new team($row['visitorID']);
$surv_pick_options_h[$i]=$row['homeID'];
$surv_pick_options_v[$i]=$row['visitorID'];
if ($row['expired']){
$surv_pick_expired_h[$i]=$row['homeID'];
$surv_pick_expired_v[$i]=$row['visitorID'];
}
$surv_gameID[$i] = (int)$row['gameID'];
$i++;
$rowclass = (($i % 2 == 0) ? ' class="altrow"' : '');
}
};
Drop down select option:
$sWeek = (int)getCurrentWeek()+1;
if ($week < $sWeek){
$survpicks_to_disable = array_slice($survpicks,0,$week-1);
$disabled = array_merge($survpicks_to_disable,$surv_pick_expired_h,$surv_pick_expired_v);
echo '<select name="survpick" id="survpick">
<option default>Select</option>';
foreach($surv_pick_options_h as $home){
echo '<option value="'.$home.'"'.(in_array($home,$disabled)?' style="background-color:pink" disabled':'').($home == $currentID?' selected':'').'>'.$home.'</option>';
}
foreach($surv_pick_options_v as $visitor){
echo '<option value="'.$visitor.'"'.(in_array($visitor,$disabled)?' style="background-color:pink" disabled':'').($visitor == $currentID?' selected':'').'>'.$visitor.'</option>';
}
}
echo '</select>';
}
And finally update a table with results:
$sql = "insert into " . DB_PREFIX . "picksurvivor (weekNum, userID, user, gameID, picksurv, showPicks) values (" . $_POST['week'] . ", " . $user->userID . ",'" . $user->userName . "', '" . $surv_gameID . "', '" . $_POST['survpick'] . "', ". (int)$_POST['showPicks'] . ");";
$mysqli->query($sql) or die('Error deleting survivor pick: ' . $mysqli->error);
I found a different approach, doing an update after the insert to basically brute force the gameID in there.

PHP numbering by unique ID grouping

I want to auto numbering but by user group
Query :
$query = "select distinct(DATE_FORMAT(a.in_time, '%Y%m%d')) as in_time, a.user_id, a.notes, b.nama from attendance a left join dat_login b on(a.user_id=b.ID) where DATE_FORMAT(a.in_time, '%Y')='2017' and DATE_FORMAT(a.in_time, '%M')='April' and id_shop!=2 order by b.nama asc";
$querynm = "select distinct(b.nama) as nama from attendance a left join dat_login b on(a.user_id=b.ID) where DATE_FORMAT(a.in_time, '%Y')='2017' and DATE_FORMAT(a.in_time, '%M')='April' group by b.nama order by b.nama asc";
$stid = mysqli_query($conn, $query) or die (mysqli_error($conn));
$stnm = mysqli_query($conn, $querynm) or die (mysqli_error($conn));
Result :
$alphabet_start = 'A';
while ($data = mysqli_fetch_assoc($stid)) {
$data['user_id'] += 1;
$no_cell = 11;
echo $data['nama'] . " ";
echo $data['user_id'] . " ";
if ($data['notes']=="") {
echo chr(ord("A") + date('d', strtotime($data['in_time']))) . $no_cell . " - " . chr(ord("A") + date('d', strtotime($data['in_time']))) . ". " . "Masuk <br>";
} else if ($data['notes']=="S") {
echo chr(ord("A") + date('d', strtotime($data['in_time']))) . $no_cell . " - " . chr(ord("A") + date('d', strtotime($data['in_time']))) . ". " . "Sakit <br>";
} else if ($data['notes']=="L") {
echo chr(ord("A") + date('d', strtotime($data['in_time']))) . $no_cell . " - " . chr(ord("A") + date('d', strtotime($data['in_time']))) . ". " . "Libur <br>";
}
$alphabet_start++;
$no_cell++;
$data['user_id']++;
}
But, the value showing like this :
I want the value showing like this :
As you can see the number is changing in the next name, how to do it ?
Sorry for my bad grammar. Thanks before :)
Your code is a bit confusing but I think I understand what you mean.
You can do it as such:
$alphabet_start = 'A';
$userID = "";
$cells = array();
$cellNum = 11;
while ($data = mysqli_fetch_assoc($stid)) {
$data['user_id'] += 1;
if (in_array($data['user_id'], $cells)) {
$no_cell = $cellNum;
} else {
$no_cell = ($cellNum += 1);
$cells[] = $data['user_id'];
}
echo $data['nama'] . " ";
echo $data['user_id'] . " ";
if ($data['notes'] == "") {
echo chr(ord("A") + date('d', strtotime($data['in_time']))) . $no_cell . " - " . chr(ord("A") + date('d', strtotime($data['in_time']))) . ". " . "Masuk <br>";
} else if ($data['notes'] == "S") {
echo chr(ord("A") + date('d', strtotime($data['in_time']))) . $no_cell . " - " . chr(ord("A") + date('d', strtotime($data['in_time']))) . ". " . "Sakit <br>";
} else if ($data['notes'] == "L") {
echo chr(ord("A") + date('d', strtotime($data['in_time']))) . $no_cell . " - " . chr(ord("A") + date('d', strtotime($data['in_time']))) . ". " . "Libur <br>";
}
$alphabet_start++;
$no_cell++;
$data['user_id']++;
}

Categories