I'm creating an array in PHP to send back to the front end for display in a Flot line chart. I have data that should be displayed year to date by month. If my SQL statement doesn't find any values for a given month, there is no array element for that month, and the Flot chart doesn't plot a data point for that month (See Mar and Apr in screenshot below). I'd like it to show a zero data point for months where there is no data.
Here's how I'm creating my array:
$array = array();
$array['data'] = Array();
$array['label'] = $tags[0]['tag_name'];
foreach($tags as $key=>$value) {
$month = $value['month'];
$arr = Array($month, $value['trans_amount']);
array_push($array['data'], $arr);
}
Current output:
{"data":[[1,"75.00"],[2,"170.00"],[5,"100.00"]],"label":"example label"}
Desired output:
{"data":[[1,"75.00"],[2,"170.00"],[3, "0"],[4, "0"],[5,"100.00"]],"label":"example label"}
and here's how the chart currently displays with the current output:
This works. It's a slight modification of your foreach loop. You need an extra variable $monthVal keep track of the current month.
//Assuming this the month uptil which you want the data.
$current_month = 7;
$monthVal = 1;
foreach($tags as $key=>$value) {
$month = $value['month'];
if($month != $monthVal){
while($month != $monthVal){
$array['data'][] = Array($monthVal, "0");
$monthVal += 1;
}
}
$arr = Array($month, $value['trans_amount']);
array_push($array['data'], $arr);
$monthVal += 1;
}
//This loop is added to append the array if the last entry is not equal to $current_month.
while($monthVal <= $current_month){
$array['data'][] = Array($monthVal, "0");
$monthVal += 1;
}
This should work. What I do is check if there is a missing months and then populate that month with zero as value.
$currMonth = 1;
foreach($tags as $key=>$value) {
$month = $value['month'];
if($month != $currMonth){
//if we are missing some months populate that month with zero as value
while($month != $currMonth){
array_push($array['data'],Array($currMonth, "0"));
$currMonth++;
}
}
$arr = Array($month, "'" . $value['trans_amount'] . "'");
array_push($array['data'], $arr);
$currMonth++;
}
echo json_encode($array);
I would change your SQL query to return more data, if it is stored as a date.
Try to maintain dates as dates rather than integers. PHP and SQL date functions are extensive and useful.
This simple for loop will fill the array with the missing data from the SQL query before the foreach.
for($i=1;$i<=12;$i++){
if(!isset($tags[$i])){
$tags[$i]['month'] = $i;
$tags[$i]['trans_amount'] = 0;
}
}
foreach($tags as $key=>$value) {
$month = $value['month'];
$arr = array($month, $value['trans_amount']);
array_push($array['data'], $arr);
}
Try this (works in PHP 5.3+):
$array = array();
$month_min = $month_max = 0;
foreach($tags as $value) {
$month = $value['month'];
$array[$month - 1] = array($month, $value['trans_amount']);
$month_max = $month;
if (!$month_min) $month_min = $month;
}
$months = array_values(array_map(function ($v) { return intval($v['month']); }, $tags));
$months_range = range(1, $month_max);
foreach (array_diff($months_range, $months) as $month) {
$array[$month - 1] = array($month, 0);
}
$result = array(
'data' => array_slice($array, $month - 1),
'label' => $tags[0]['tag_name'],
);
print_r(json_encode($result));
Related
I have this array.
$val = array(12:10, 4:16, 2:05);
I want to subtract 14:00 hrs from the $val array in the way that from every element that element do not become negative like this:
$val = array(0, 2:26, 2:05)
<?php
$input = "14:00";
$val = array("12:10", "4:16", "2:05");
function timeSubtractionFirstTime($actual_time ,$time_to_reduce){
$actual_time_array = explode(":",$actual_time);
$time_to_reduce = explode(":",$time_to_reduce);
$final_result = [];
if($actual_time_array[1] < $time_to_reduce[1]){
$actual_time_array[0] = $actual_time_array[0]-1;
$final_result[] = $actual_time_array[1]+60-$time_to_reduce[1];
}else{
$final_result[] = $actual_time_array[1]-$time_to_reduce[1];
}
$final_result[] = $actual_time_array[0]-$time_to_reduce[0];
return implode(":", array_reverse($final_result));
}
$timeToReduceLeft = $input;
foreach ($val as &$value) {
$diff = timeSubtractionFirstTime($value, $timeToReduceLeft);
if (strpos($diff, chr(45)) !== false){ //if $value < $timeToReduceLeft
$timeToReduceLeft = timeSubtractionFirstTime($timeToReduceLeft, $value);
$value = "00:00";
}
else { //if $value >= $timeToReduceLeft
$value = timeSubtractionFirstTime($value, $timeToReduceLeft);
$timeToReduceLeft = "00:00";
}
if ($timeToReduceLeft == "00:00"){
break;
}
}
echo implode(",", $val);
I get the function to extract time from this post and implement the logic for your problem as follows:
We substract the time from input value until the input value become zero or entire array elements become zero (by forloop).
This solution also works with input or array elements value greater than "24:00".
I have
$array = array(
'AUS200JAN',
'GOLD300MAR',
'AUS200_h18',
'GOLD300_g19',
'EURUSDJUL18',
'AUSEURNOV18',
);
I would like to know an efficient way to find out if the array values contain the initial 3 letters of a month. So in this array there JAN, MAR, JUL18, NOV18.
So far I am doing it this way but would like to know if there is a more efficient way to approach this problem.
//Creating an Array of letters for months
$montharray = array(
'JAN','FEB','MAR','APR',''MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'
);
foreach($montharray as $month) {
foreach($array as $val) {
if(strpos($val,$month) !== FALSE) {
var_dump('has month');
} else {
var_dump('Does not contain month');
}
}
}
<?php
$array = array(
'AUS200JAN',
'GOLD300MAR',
'AUS200_h18',
'GOLD300_g19',
'EURUSDJUL18',
'AUSEURNOV18',
);
$months = array();
for ($i = 0; $i < 12; $i++) {
$timestamp = mktime(0, 0, 0, date('f') - $i, 1);
$months[date('n', $timestamp)] = date('M', $timestamp);
}
echo '<pre>';
print_r($months);
foreach($months as $row){
if(preg_grep( "/$row/i" , $array )){
echo 'found';
echo '</br>';
}
else{
echo 'not found';
echo '</br>';
}
}
You can try something like this. It checks the array records for each month (3 letters format)
I have 3 tables of data stored in a database each containing a date and a time field. I'm pulling all the relevant data from each table and concatenating them to an array. I now need to sort the array on date first and then time. I'm currently sorting by date at that works fine but the time sometimes can be right and is sometimes wrong
What I'm currently using to gather the data:
$results = [];
$sql_assign = mysql_query("SELECT * FROM `tk_assign` WHERE ticket_id = $tk_id");
$sql_update = mysql_query("SELECT * FROM `tk_update` WHERE ticket_id = $tk_id");
$sql_status = mysql_query("SELECT * FROM `tk_status_change` WHERE ticket_id = $tk_id");
while($row = mysql_fetch_assoc($sql_assign)){
$results[] = $row;
}
while($row = mysql_fetch_assoc($sql_update)){
$results[] = $row;
}
while($row = mysql_fetch_assoc($sql_status)){
$results[] = $row;
}
What I'm using to sort it
$orderByDate = $my2 = array();
foreach($results as $key=>$row)
{
$my2 = explode('/',$row['date']);
$my3 = explode('/',$row['time']);
$my_date2 = $my2[1].'/'.$my2[0].'/'.$my2[2];
$orderByDate[$key] = strtotime($my_date2);
}
$sorted = array_multisort($orderByDate, SORT_ASC, $results);
I've thought about turning it into timecodes but that hasn't worked either. Any help would be greatly appreciated
Example time and date:
Date: 22/09/2015 Time: 15:32:12
Date: 22/09/2015 Time: 14:50:28
Date: 25/09/2015 Time: 12:21:58
I think this line is wrong:
$my3 = explode('/',$row['time']);
It probably should be:
$my3 = explode(':',$row['time']);
In any case, you're not even using the $my3 variable in your sorting algorithm.
Here's another solution. Just after merging the arrays, add the following code:
for ($i =0; $i < count($results); $i++){
$results[$i]['datetime'] = $results[$i]['date'].' '.$results[$i]['time'];
}
function compareDateTime($a, $b) {
$mya = new DateTime();
$mya->createFromFormat('d/m/Y H:i:s', $a['datetime']);
$myb = new DateTime();
$myb->createFromFormat('d/m/Y H:i:s', $b['datetime']);
if ($mya == $myb)
return 0;
if ($mya > $myb)
return 1;
return -1;
}
usort($results, 'compareDateTime');
If you are using PHP > 5.2 then you should use following way.
$orderByDate = $my2 = array();
foreach($results as $key=>$row)
{
$myDateTime = DateTime::createFromFormat('d/m/Y', $date);
$newDateString = $myDateTime->format('Y-m-d');
$orderByDate[$key] = strtotime($newDateString." ".$row['time']);
}
$sorted = array_multisort($orderByDate, SORT_ASC, $results);
i have starting date ..
i need to add months in starting date inside for loop
for ex -
startingdate = 25-03-2015
and my loop runs two time then it generate like below
25-04-2015
25-05-2015
thats it...
$startingdate = $_POST['startingdate'];
$dates = date("d-m-Y", strtotime($startingdate . " +" . " 1MONTHS -1 DAYS"));
for ($i = 0; $i <= 2; $i++)
{
$coupondate = $dates;
}
If your results are returned with commas separting. Then use explode() to return an array of values. Then using max() and min() in php you can set your lower and upper limits to loop through.
But if you're getting all the results anyway, explode() should do the trick, then just loop through them.
$result = "100,101,102,103";
$arr = explode(",", $result);
foreach ($arr as $number) {
echo $number;
}
Or with min / max:
$result = "100,101,102,103";
$arr = explode(",", $result);
$min = min($arr);
$max = max($arr);
for ($i = $min; $i <= $max; $i++) {
echo $i;
}
Take a look at
min() and
max()
$points=array(500,501,502,503,504,505,506);
$min=min($points);
$max=max($points);
for($i=$min;$i<$max+1;++$i{
//do something
}
If your data is stored lower to upper :
$text = '500,501,502,503,504,505,506';
$explode = explode(',',$text);
$index = count($explode)-1;
for ($i=$explode[0]; $i<=$explode[$index]; $i++)
{
echo $i;
}
If order can change, add :
sort($explode);
Try this :
//after connected with a database
$data = (explode(",", $rows["points"]));
for ($i=min($data); $i<=max($data); $i++)
{
}
Note : If the separation between words is ', ' (a comma and space) then change with this :
$data = (explode(", ", $rows["points"]));
I've spent a long time on this problem, and I cannot for the life of me figure it out. Any help will be much appreciated!
I have an array of strings, which I am using to get information from, i.e. the month of an event is hidden within the url (the string), and I want to cycle through all the urls and get the month, and other data out and make each data-piece it's own array.
Here's the deal, I can do it twice successfully, but the third time I try to create an array, it breaks down.
This code works:
$months = array();
$times = array();
foreach ($ticketsLinks as $ticketsLink){
//CREATE VENUE ARRAY
// Delete all the way up to "-tickets-"
$findMeA = '-tickets-';
$posA = strpos($ticketsLink, $findMeA);
$posA = $posA + 9;
$venue = substr($ticketsLink, $posA);
// Find the first number in the string - delete everything after that.
$lengthA = strlen($venue);
$parts = str_split($venue);
$first_num = -1;
$num_loc = 0;
foreach ($parts AS $a_char) {
if (is_numeric($a_char)) {
$first_num = $num_loc;
break;
}
$num_loc++;
}
$posB = -$lengthA + $num_loc - 1;
$venue = substr($venue, 0, $posB);
// Replace dashes with spaces.
$venue = str_replace("-"," ",$venue);
//Add value to venue's array
$venues[] = $venue;
// CREATE TIME ARRAY
$pos = strrpos($ticketsLink, '-');
$pos = strlen($ticketsLink) - $pos - 1;
$time = substr($ticketsLink, -$pos);
$pos = strpos($time, '/');
$time = substr($time, 0, $pos);
$times[] = $time;
}
This code does not:
$months = array();
$times = array();
$years = array();
foreach ($ticketsLinks as $ticketsLink){
//CREATE VENUE ARRAY
// Delete all the way up to "-tickets-"
$findMeA = '-tickets-';
$posA = strpos($ticketsLink, $findMeA);
$posA = $posA + 9;
$venue = substr($ticketsLink, $posA);
// Find the first number in the string - delete everything after that.
$lengthA = strlen($venue);
$parts = str_split($venue);
$first_num = -1;
$num_loc = 0;
foreach ($parts AS $a_char) {
if (is_numeric($a_char)) {
$first_num = $num_loc;
break;
}
$num_loc++;
}
$posB = -$lengthA + $num_loc - 1;
$venue = substr($venue, 0, $posB);
// Replace dashes with spaces.
$venue = str_replace("-"," ",$venue);
//Add value to venue's array
$venues[] = $venue;
// CREATE TIME ARRAY
$pos = strrpos($ticketsLink, '-');
$pos = strlen($ticketsLink) - $pos - 1;
$time = substr($ticketsLink, -$pos);
$pos = strpos($time, '/');
$time = substr($time, 0, $pos);
$times[] = $time;
// CREATE YEAR ARRAY
$pos = strrpos($ticketsLink, '-');
$pos = strlen($ticketsLink) - $pos - 1;
$year = substr($ticketsLink, -$pos);
$pos = strpos($year, '/');
$year = substr($year, 0, $pos);
$years[] = $year;
}
For the purposes of this example, I kept the code to get the year string and the time string exactly the same to show that that wasn't the problem. I've gone through the above code and tried to debug it - the only thing that's making it not work is when I push the year variable to the years array.
--- UPDATED TO INCLUDE NEW INFORMATION -----
Unfortunately, breaking apart the URL to get the requisite information is the best way to do this - the URLs are coming from a CSV feed.
So, after the first foreach, then just for a test, I run a foreach loop through the $years array -
foreach($years as $year){
echo $year;
}
Eventually, the $years array will be passed to a mySQL database, but for now, I just want to make sure I'm processing the URL correctly. The resultant loop should look something like this:
2014
2015
2014
2016
Instead, I get nothing, and all the code after the first foreach (where I'm breaking down the URL), doesn't run. I have an echo at the bottom that echos "This code works!", and it doesn't print to the screen when I try to push values to the $years array.