With the code below, I am trying to return all the items in item.children. I don't understand why it isn't returning the last item. After logging the results at several places and verifying SQLs, I could finally conclude the part of the code below in a file that is accessed via ajax is creating the array without the last record in the SQL result. I am still unable to find where it is missing the last record to be added to the array $skus.
case 'skuLookup':
$sql = "SELECT i.id, i.sku as parentSku, i.description as parentDescription, sku.item_sku as sku, sku.description FROM sku LEFT JOIN sku_vendor_pivot AS vp ON sku.id = vp.sku_vendor_fk LEFT JOIN sku_internal AS i ON i.id = vp.sku_fk WHERE i.sku LIKE '" . $dbh->escape($call['id']) . "%' AND i.id is not null";
$sql .= " UNION ";
$sql .= "SELECT i.id, i.sku as parentSku, i.description as parentDescription, sku.item_sku as sku, sku.description FROM sku LEFT JOIN sku_vendor_pivot AS vp ON sku.id = vp.sku_vendor_fk LEFT JOIN sku_internal AS i ON i.id = vp.sku_fk WHERE sku.item_sku LIKE '" . $dbh->escape($call['id']) . "%' AND i.id is not null";
if(is_numeric($call['id'])) {
$sql = "SELECT i.id, i.sku as parentSku, i.description as parentDescription, sku.item_sku as sku, sku.description FROM sku LEFT JOIN sku_vendor_pivot AS vp ON sku.id = vp.sku_vendor_fk LEFT JOIN sku_internal AS i ON i.id = vp.sku_fk WHERE i.id = " . $dbh->escape($call['id']) . " AND i.id is not null";
}
$skus = array();
if($dbh->query($sql)) {
$parent = null;
$children = array();
$count = 0;
while($dbh->next_record()) {
$count++;
if($parent == null) {
$parent = $dbh->Record['id'];
}
if($parent != $dbh->Record['id']) {
$sku['children'] = $children;
$skus[] = $sku;
$parent = $dbh->Record['id'];
$children = array();
}
$sku = array(
'description' => $dbh->Record['parentDescription'],
'value' => $dbh->Record['parentSku'],
);
$children[] = $dbh->Record['sku'] . " - " . $dbh->Record['description'];
}
if($count == 1) {
$sku['children'] = $children;
$skus[] = $sku;
}
}
$newData['skuLookup']['data'] = $skus;
error_log("newData['skuLookup']['data'] data:\n" . print_r($newData['skuLookup']['data'], TRUE));
$data = array_merge($data,$newData);
break;
In the loop, the code sets up $sku and appends an element to the $children array:
while($dbh->next_record()) {
$count++;
// ...
$sku = [ ... ];
$children[] = $dbh->Record['sku'] ...;
}
But on the last iteration, those variables are only used if count == 1, ie if there was only 1 record at all:
if($count == 1) {
$sku['children'] = $children;
$skus[] = $sku;
}
If I am understanding correctly, it looks like maybe those values are normally used on the next iteration, inside the if($parent != $dbh->Record['id']) { test. But that won't happen for any values set up on the last record.
How do you add columns to an action button such as the detail button in AJAX? This is my code:
Controller:
public function ajax_list()
{
$list = $this->th_ajaran->get_datatables();
$data = array();
$no = $_POST['start'];
$tools = $_POST['start'];
foreach ($list as $th_ajaran) {
$no++;
$row = array();
$row[] = $no;
$row[] = $th_ajaran->nama_kelas;
$row[] = $th_ajaran->jurusan;
$data[] = $row;
}
$output = array(
"draw" => $_POST['draw'],
"recordsTotal" => $this->th_ajaran->count_all(),
"recordsFiltered" => $this->th_ajaran->count_filtered(),
"data" => $data,
);
//output to json format
echo json_encode($output);
}
This is My Model
<?php
class Th_Ajaran_kelas_model extends CI_Model {
var $table = 'th_ajaran';
var $column_order = array(null, 'nama_kelas','jurusan'); //set column field database for datatable orderable
var $column_search = array('nama_kelas','jurusan'); //set column field database for datatable searchable
var $order = array('th_ajaran' => 'asc'); // default order
private function _get_datatables_query()
{
//add custom filter here
if($this->input->post('th_ajaran'))
{
$this->db->where('th_ajaran', $this->input->post('th_ajaran'));
}
if($this->input->post('nama_kelas'))
{
$this->db->like('nama_kelas', $this->input->post('nama_kelas'));
}
if($this->input->post('jurusan'))
{
$this->db->like('jurusan', $this->input->post('jurusan'));
}
$this->db->from($this->table);
$this->db->join('th_ajaran_kelas', 'th_ajaran_kelas.id_th_ajaran = th_ajaran.id_th_ajaran');
$this->db->join('kelas', 'th_ajaran_kelas.id_kelas = kelas.id_kelas');
$i = 0;
foreach ($this->column_search as $item) // loop column
{
if($_POST['search']['value']) // if datatable send POST for search
{
if($i===0) // first loop
{
$this->db->group_start(); // open bracket. query Where with OR clause better with bracket. because maybe can combine with other WHERE with AND.
$this->db->like($item, $_POST['search']['value']);
}
else
{
$this->db->or_like($item, $_POST['search']['value']);
}
if(count($this->column_search) - 1 == $i) //last loop
$this->db->group_end(); //close bracket
}
$i++;
}
if(isset($_POST['order'])) // here order processing
{
$this->db->order_by($this->column_order[$_POST['order']['0']['column']], $_POST['order']['0']['dir']);
}
else if(isset($this->order))
{
$order = $this->order;
$this->db->order_by(key($order), $order[key($order)]);
}
}
public function get_datatables()
{
$this->_get_datatables_query();
if($_POST['length'] != -1)
$this->db->limit($_POST['length'], $_POST['start']);
$query = $this->db->get();
return $query->result();
}
Javascript
var table;
$(document).ready(function() {
//datatables
table = $('#table').DataTable({
"processing": true, //Feature control the processing indicator.
"serverSide": true, //Feature control DataTables' server-side processing mode.
"order": [], //Initial no order.
// Load data for the table's content from an Ajax source
"ajax": {
"url": "",
"type": "POST",
"data": function ( data ) {
data.th_ajaran = $('#th_ajaran').val();
}
},
//Set column definition initialisation properties.
"columnDefs": [
{
"targets": [ 0 ], //first column / numbering column
"orderable": false, //set not orderable
},
],
});
$('#btn-filter').click(function(){ //button filter event click
table.ajax.reload(); //just reload table
});
$('#btn-reset').click(function(){ //button reset event click
$('#form-filter')[0].reset();
table.ajax.reload(); //just reload table
});
});
I am having to solve a problem involving code in both JS and PHP. For some reason, whenever this code executes, it puts the first entry in all the rows of the table instead of iterating through each entry and putting all of them in the rows. I would appreciate someone's help in giving me insights into how to fix this issue. Can this be fixed with just a "for in" loop? Thanks in advance.
<?php include('../../functions.php');
$query = "
SELECT
*
FROM
plobby
LEFT JOIN users ON users.UID = plobby.UID
WHERE
`LID` = '". preg_replace("/[^A-Za-z0-9 ]/", '', $_POST['id']) ."';
";
$sql = "SELECT COUNT(`LID`) AS `x` FROM `snipe`.`plobby` WHERE LID = '".$_POST['id']."';";
$result = $db->query($query);
$rst = $db->query($sql);
$cnt = 0;
if($rst->num_rows > 0)
while($row = $rst->fetch_assoc())
$cnt = $row["x"];
if ($result->num_rows > 0)
for($i = 1;$i<= $cnt;$i++)
echo json_encode($result->fetch_assoc());
else
echo json_encode([]);
?>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Here is the object to which the above loop is referring:
<script type="text/javascript">
var state = {};
for($i = 1;$i <= <?php echo getLobbytPlayers($_GET['id']);?>;$i++ ){
var reloadTable = function (data) {
if ($.data(state) == $.data(data)) {
return;
}
$('#js-lobby-table').empty();
$.each(data, function (rowNumber, rowData) {
var row = $('<tr>');
console.log(data);
// Player
row.append($('<td>', {
'html': data.eName
}));
// Status
row.append($('<td>', {
'html': data.gameID == "000" ? 'waiting' : 'ingame'
}));
// Win %
row.append($('<td>', {
'html': 'TODO'
}));
// Games
row.append($('<td>', {
'html': 'TODO'
}));
// K/D
row.append($('<td>', {
'html': 'TODO'
}));
$('#js-lobby-table').append(row);
});
// Set the current table state.
state = data;
};
}
setInterval(function () {
$.ajax({
type: 'POST',
url: '/lobby/api/table.php',
data: {
id: '<?= $_GET['id'] ?>'
},
success: reloadTable,
dataType: 'json'
});
}, 10);
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You shouldn't call json_encode() multiple times. The response has to contain a single JSON object, not multiple objects. You need to put all the results in an array, and call json_encode() on that array at the end.
There's also no need to get the count first. Just call fetch_assoc() until you get all the results.
<?php include('../../functions.php');
$query = "
SELECT
*
FROM
plobby
LEFT JOIN users ON users.UID = plobby.UID
WHERE
`LID` = '". preg_replace("/[^A-Za-z0-9 ]/", '', $_POST['id']) ."';
";
$result = $db->query($query);
$rows = [];
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
echo json_encode($rows);
?>
I have a form which has a Date From and To Date selector then a generate button, upon clicking generate button, an excel file will be the output. Question how and where do I put the loading script in my code given I'm not using ajax but rather:
$("#btnReport1").click(function() {
var page = 'export-report1?from='+$("#fromDateAll").val()+'&to='+$("#toDateAll").val();
return window.location = page;
});
And my route
Route::get('export-report1', 'ReportController#exportReport1');
function
public function exportReport1()
{
$from = Input::get('from');
$to = Input::get('to');
$query = "SELECT id, phone FROM qcv.forms WHERE calldatetime >= '$from' AND calldatetime <= '$to' ORDER BY id ASC ;";
// $query = "SELECT a.id as form_id, a.phone, b.metrics_id, b.response, c.metrics_name, c.description, c.question
// FROM forms a
// INNER JOIN forms_responses b ON a.id = b.form_id
// INNER JOIN metrics c ON c.id = b.metrics_id LIMIT 10";
$phone = DB::connection('mysql')->select($query);
if(!empty($phone))
{
Excel::create('Laravel Excel', function($excel) use ($phone) {
return $excel->sheet('Excel sheet', function($sheet) use ($phone) {
$sheet->setOrientation('landscape');
$sheet->cell('A9', 'KEY QUALITY METRICS');
$sheet->cell('B9', 'DESCRIPTIONS');
$sheet->cell('C9', 'ASSESSMENT QUESTION');
$sheet->cells('A9:C9', function($cells) {
$cells->setFontWeight('bold');
$cells->setFontColor('#DF013A');
});
$metrics = Metric::all();
$metric_start = 10;
$start = "D";
$count = 10;
foreach ($phone as $key => $value2) // Populate Phone Numbers Horizontally
{
$sheet->cell($start.'9', $value2->phone);
// This will fill the responses for each number
foreach ($metrics as $key => $value)
{
$responses = FormResponses::where('form_id', '=', $value2->id)->where('metrics_id', '=', $value->id)->get();
$sheet->cell($start.$count, $responses[0]->response);
$sheet->cell('C'.$count, $value->question);
$sheet->cell('B'.$count, $value->description);
$sheet->cell('A'.$count, $value->metrics_name);
$count++;
}
$start++;
$count = 10;
}
});
})->export('xls');
}
else
{
return "No records found.";
}
}
Essentially, the purpose is to compare what categories of tasks each member on my team is performing on a weekly basis.
and I would like to add number of Week underneath the Axes instead of 1.0 , 2.0 and 3.0 .
I am getting wrong result as its only showing 1 for excellent and for all week1, week2, week3, week4
I selected starting day 1/12/2014 and the end date is 31/12/2014 so I was expecting to have 1 for bad and two for good and three for excellent.
This is my PHP code
<?php>
$result = mysqli_query($con,"SELECT * FROM `employees` WHERE `Date` BETWEEN '" . $_POST
['start'] . "' AND '" . $_POST ['end'] . "' ") or die ("Error: ".mysqli_error($con));
$Levels = 0;
$Levelscounter=0;
$countergood=0;
$counterbad=0;
while($row = mysqli_fetch_array($result))
{
$answer = $row['level'];
$bad = 'bad';
$good='good';
$excellent='excellent';
if ($answer == $bad)
{
$counterbad++;
}
if($answer == $good)
{
$countergood++;
}
if($answer == $excellent)
{
$counterexcellent++;
}
$Levelscounter;
}
mysqli_close($con);
?>
Here is my JavaScript Code:
<script type="text/javascript">
(function($) {
var series = [{
data: [[ 1,<?php echo $counterbad; ?>] ],
valueLabels: {
show: true,
valign: 'middle'
} ,
label: "Low"
},
{
data: [[1,<?php echo $countergood; ?>]],
valueLabels: {
show: true,
valign: 'middle'
} ,
label: "Medium"
}, {
data: [[1,<?php echo $counterexcellent; ?>]],
valueLabels: {
show: true,
valign: 'middle'
} ,
label: "High"
}];
var options = {
xaxis: {
minTickSize: 1
},
series: {
bars: {
show: true,
barWidth: .8,
align: "center"
},
stack: true
}
};
$.plot("#placeholder", series, options);
})(jQuery);
</script>
I got the levels displayed in the stacked chart and it is working fine regarding from the start and end date I select but I could display this result as a weekly result.
I would like to get ideas what do I need to add ? Any ideas please ?
Is there a function in PHP that sort out this ?
Thank you.
Updating
As you can see in the image numbers on each series related to bad, good, excellent.
red for bad and good for blue and yellow for excellent.
To add weeks/textual data underneath the columns you have to add the library's categories file jquery.flot.categories.min.js to your javascript assets.
If i understand you correctly you want the chart to look like this
Javascript
You need to add these files in
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="jquery.flot.min.js"></script>
<script src="jquery.flot.categories.min.js"></script>
<script src="jquery.flot.stack.min.js"></script>
and initialize the library we will talk about $output after this code
<div id="placeholder" style="width:818px;height:413px" ></div>
<script type="text/javascript">
$(function() {
var series = [<?php echo $output; ?>];
$.plot("#placeholder", series, {
series: {
stack:true,
lines:{fill:true,show:false,steps:false},
bars: {
show: true,
barWidth: 0.8,
align: "middle",
},
},
xaxis: {
mode: "categories",
minTickSize: 1
}
});
});
PHP
First you need to query the database to find the date between the specified dates, after getting the result you have to sort the data for each week in an array
For instance week One => 'good','good','bad','bad', 'week two' => and so on ...
after that you can use array_count_values() to count the number of occurrences and build
the charts column.
I simplified the code using functions to make it easier for you
<?php
$con = mysqli_connect("localhost", 'root','','your db');
function getChartData($con, $startDate, $endDate){
$startDate = date("Y-m-d H:i:s", strtotime($startDate));
$endDate = date("Y-m-d H:i:s", strtotime($endDate));
$query = "SELECT * FROM `employees` WHERE `date` BETWEEN '$startDate' AND '$endDate'";
$result = mysqli_query($con, $query) or die ("Error: ".mysqli_error($con));
// a multidimenional array containing each week with it's
$weeksData = [];
// Group each week with it's data
while($row = mysqli_fetch_array($result)){
$weekNumber = date("W", strtotime($row['date']));
if(isset($weeksData[$weekNumber]))
{
$weeksData[$weekNumber][] = $row['level'];
}
$weeksData[$weekNumber][] = $row['level'];
}
// reset array indexes and sort the array
sort($weeksData);
$data = array();
// using array_count_values to count the number of (good, bad and excellent)
foreach ($weeksData as $key => $week) {
$data[$key] = array_count_values($week);
}
// return all the weeks with number of (good, bad and excellent) occurences
return $data;
}
// build the javascript object {data:['week num', occuerences]}
function buildColumn($data,$label, $numberOfWeeks)
{
$data = array_column($data,strtolower($label));
$balance = $numberOfWeeks - count($data);
if($balance !=0){
for($i=1;$i<=$balance;$i++) {
$data[] = 1;
}
}
$string = '{data: [';
foreach ($data as $key => $value) {
$weekNumber = $key+1;
$string .= '["Week '.$weekNumber.'",'.$value.'],';
}
$string = rtrim($string, ',');
$string .= "],valueLabels: {show: true,valign: 'middle'},label: '$label'}";
return $string;
}
function getNumberofWeeks($startDate, $endDate){
$weeks = array();
$period = new DatePeriod(new DateTime($startDate),
DateInterval::createFromDateString('+1 day'),new DateTime($endDate)
);
foreach ( $period as $dt ) {
$weeks[] = $dt->format( 'W' );
}
return count(array_unique($weeks));
}
now you can easily use these functions like this
$numberOfWeeks = getNumberofWeeks($_POST['start'],$_POST['end']);
// get data of the last number of weeks
$chartData = getChartData($con, $_POST['start'],$_POST['end']);
// bulding columns data for each occurence
$badColumn = buildColumn($chartData,'Bad', $numberOfWeeks);
$goodColumn = buildColumn($chartData,'Good', $numberOfWeeks);
$excellentColumn = buildColumn($chartData,'Excellent', $numberOfWeeks);
// output {data: ...}, {data: ...},{data:....}
$output = "$excellentColumn , $goodColumn , $badColumn";
Full working Example
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="jquery.flot.min.js"></script>
<script src="jquery.flot.categories.min.js"></script>
<script src="jquery.flot.stack.min.js"></script>
</head>
<body>
<?php
$con = mysqli_connect("localhost", 'root','','your db');
function getChartData($con, $startDate, $endDate){
$startDate = date("Y-m-d H:i:s", strtotime($startDate));
$endDate = date("Y-m-d H:i:s", strtotime($endDate));
$query = "SELECT * FROM `employees` WHERE `date` BETWEEN '$startDate' AND '$endDate'";
$result = mysqli_query($con, $query) or die ("Error: ".mysqli_error($con));
// a multidimenional array containing each week with it's
$weeksData = [];
// Group each week with it's data
while($row = mysqli_fetch_array($result)){
$weekNumber = date("W", strtotime($row['date']));
if(isset($weeksData[$weekNumber]))
{
$weeksData[$weekNumber][] = $row['level'];
}
$weeksData[$weekNumber][] = $row['level'];
}
// reset array indexes and sort the array
sort($weeksData);
$data = array();
// using array_count_values to count the number of (good, bad and excellent)
foreach ($weeksData as $key => $week) {
$data[$key] = array_count_values($week);
}
// return all the weeks with number of (good, bad and excellent) occurences
return $data;
}
// build the javascript object {data:['week num', occuerences]}
function buildColumn($data,$label, $numberOfWeeks)
{
$data = array_column($data,strtolower($label));
$balance = $numberOfWeeks - count($data);
if($balance !=0){
for($i=1;$i<=$balance;$i++) {
$data[] = 1;
}
}
$string = '{data: [';
foreach ($data as $key => $value) {
$weekNumber = $key+1;
$string .= '["Week '.$weekNumber.'",'.$value.'],';
}
$string = rtrim($string, ',');
$string .= "],valueLabels: {show: true,valign: 'middle'},label: '$label'}";
return $string;
}
function getNumberofWeeks($startDate, $endDate){
$weeks = array();
$period = new DatePeriod(new DateTime($startDate),
DateInterval::createFromDateString('+1 day'),new DateTime($endDate)
);
foreach ( $period as $dt ) {
$weeks[] = $dt->format( 'W' );
}
return count(array_unique($weeks));
}
// the number of weeks that you want to display in the chart
$numberOfWeeks = getNumberofWeeks($_POST['start'],$_POST['end']);
// get data of the last number of weeks
$chartData = getChartData($con, $_POST['start'],$_POST['end']);
// bulding columns data for each occurence
$badColumn = buildColumn($chartData,'Bad', $numberOfWeeks);
$goodColumn = buildColumn($chartData,'Good', $numberOfWeeks);
$excellentColumn = buildColumn($chartData,'Excellent', $numberOfWeeks);
// output {data: ...}, {data: ...},{data:....}
$output = "$excellentColumn , $goodColumn , $badColumn";
?>
<div id="placeholder" style="width:818px;height:413px" ></div>
<script type="text/javascript">
$(function() {
var series = [<?php echo $output; ?>];
$.plot("#placeholder", series, {
series: {
stack:true,
lines:{fill:true,show:false,steps:false},
bars: {
show: true,
barWidth: 0.8,
align: "middle",
},
},
xaxis: {
mode: "categories",
minTickSize: 1
}
});
});
</script>
</body>
</html>
Edit
Just replace these two functions to make it compatible with dd/mm/yyyy
function getChartData($con, $startDate, $endDate){
$startDate = explode('/', $startDate);
$startDate = $startDate[1] . '/' . $startDate[0] . '/' . $startDate[2];
$endDate = explode('/', $endDate);
$endDate = $endDate[1] . '/' . $endDate[0] . '/' . $endDate[2];
$startDate = date("Y-m-d H:i:s", strtotime($startDate));
$endDate = date("Y-m-d H:i:s", strtotime($endDate));
$query = "SELECT * FROM `employees` WHERE `date` BETWEEN '$startDate' AND '$endDate'";
$result = mysqli_query($con, $query) or die ("Error: ".mysqli_error($con));
// a multidimenional array containing each week with it's
$weeksData = [];
// Group each week with it's data
while($row = mysqli_fetch_array($result)){
$weekNumber = date("W", strtotime($row['date']));
if(isset($weeksData[$weekNumber]))
{
$weeksData[$weekNumber][] = $row['level'];
}
$weeksData[$weekNumber][] = $row['level'];
}
// reset array indexes and sort the array
sort($weeksData);
$data = array();
// using array_count_values to count the number of (good, bad and excellent)
foreach ($weeksData as $key => $week) {
$data[$key] = array_count_values($week);
}
// return all the weeks with number of (good, bad and excellent) occurences
return $data;
}
and
function getNumberofWeeks($startDate, $endDate){
$startDate = explode('/', $startDate);
$startDate = $startDate[1] . '/' . $startDate[0] . '/' . $startDate[2];
$endDate = explode('/', $endDate);
$endDate = $endDate[1] . '/' . $endDate[0] . '/' . $endDate[2];
$diff = strtotime($startDate, 0) - strtotime($endDate, 0);
return str_replace('-','', (int)floor($diff / 604800));
}