Echo 0 for Mysql query with no results - php

I'm building an array of the number of calls I have for a particular client from a mysql db on a running list of the last 30 days. The code I have so far works for adding the days that have calls to the array but I need a show a '0' for the days that have no calls (no entries in the db). Here is me code so far:
$query="SELECT COUNT(*) FROM my_db WHERE client_phone='clint_phone#' GROUP BY calldate";
$result = mysql_query($query);
$data = array();
while ($row = mysql_fetch_row($result)) {
$data[] = $row[0];
}
I just need a way to show if today I had 30 calls and yesterday I had 0, I need it to show [30,0]. What I have only would show [30].
EDIT * I have a mysql db will columns client_phone, calldate. Im looking to build a graph using the data in an array. Each point of the graph will represent a day and the number of calls for that client on that day. Im building the above query to populate that array. I'm trying to count backwards thirty days and feed the total calls for each day into the array.
EDIT 2* I've got it almost there. I'm getting a problem in the 'foreach' area. Below is the code with two print_r()'s to dump the array. The first one looks good, but the second one shows some array entries getting over-written that shouldn't be:
$query="SELECT calldate, COUNT(*) FROM my_db WHERE client_phone='phone#' and calldate>='20130101' AND calldate<='20130107' GROUP BY calldate ORDER BY calldate";
$result = mysql_query($query);
$data = array();
while ($row = mysql_fetch_array($result)) {
$data[$row['calldate']] = $row[1];
}
$startDate = '20130101';
$endDate = '20130107';
$dates = array();
for($current = $startDate; $current != $endDate; $current = date('Ymd', strtotime("$current +1 day"))) {
$dates[] = $current;
}
$dates[] = $endDate;
print_r ($data);
echo "<br />";
foreach($dates as $date){
if (in_array($date, $data)) {
// that date was found in your db_date array(therefore had queries)
}else{
$data[$date] = 0; //date was not found in your db_array so we set that date with no queries to zero
}
}
print_r ($data);
I run this in a browser and I get this:
Array ( [20130101] => 1 [20130104] => 6 [20130105] => 2 [20130106] => 1 [20130107] => 3 )
Array ( [20130101] => 0 [20130104] => 0 [20130105] => 0 [20130106] => 0 [20130107] => 0 [20130102] => 0 [20130103] => 0 )
The top output looks good, just missing a zero assigned to dates not in the data[] array. The second array has zero's in the missing dates, but other overwrited that shouldn't have been.
Thanks for any help!

Finding every date that is in that timespan and doing a task for that does not really that standard of a solution. But depending if your host allows cron-tasks; if you were able to use cron tasks to automatically insert a 0 into your database at 11:59pm for that date if no querys were made that day; you could simply extract all dates.
If you do not want to do it with cron tasks I think you can manage it this way...
$startDate = '2009-01-28';
$endDate = '2009-02-04';
$dates = array();
for($current = $startDate; $current != $endDate; $current = date('Y-m-d', strtotime("$current +1 day"))) {
$dates[] = $current;
$dates[] = $endDate;
}
then do this
foreach($dates as $date){
if (array_key_exists($date, $data)) {
// that date was found in your db_date array(therefore had queries)
}else{
$data[$date] = 0; //date was not found in your db_array so we set that date with no queries to zero
}
}
This may need some minor adjustments because I have not tested it; but this should work; if not something very close to it should. Hope this helps.

Related

PHP days difference calculation error

I have some PHP code to calculate the number of days between two specific dates. The difference should not count Sundays and Saturdays. Also, I have an array of dates, which includes holidays, which also need to be skipped.
I gave the starting date as 01-05-2015 and ending date as 01-06-2015. I gave the entire days in the month of may as array. Thus the difference should be 1 day. But I am getting the output as 7. What is the problem? Here is the code.
function dateRange($first, $last) {
$dates = array();
$current = strtotime($first);
$now = $current;
$last = strtotime($last);
while( $current <= $last ) {
if (date('w', $current) != 0){
$dates[] = date('d-m-Y', $current);
}
$current = strtotime('+1 day', $current);
}
unset($dates[0]);
return $dates;
}
$datea = "01-05-2015";
$date = "01-06-2015";
$hdsarray = array("1-05-2015","2-05-2015","4-05-2015","5-05-2015","7-05-2015","8-05-2015","9-05-2015","11-05-2015","12-05-2015","14-05-2015","15-05-2015","16-05-2015","18-05-2015","19-05-2015","21-05-2015","22-05-2015","23-05-2015","25-05-2015","26-05-2015","28-05-2015","29-05-2015","30-05-2015");
$datesarray = dateRange($datea, $date);
$result = array_diff($hdsarray,$datesarray);
$date_diff = sizeof($result);
echo $date_diff;
The only problem I can see is in the usage of array_diff, It actually includes the sat and sun which is excluded by dateRange function, if not found in holidays list.
Instead, you can pass your holiday dates in dateRange function, and filter over there.
function dateRange($first, $last, $excludeDates) {
$dates = array();
$current = strtotime($first);
$now = $current;
$last = strtotime($last);
while( $current <= $last ) {
if (date('w', $current) != 0 && date('w', $current) != 6 && !in_array(date('j-m-Y', $current), $excludeDates)){
$dates[] = date('d-m-Y', $current);
}
$current = strtotime('+1 day', $current);
}
return $dates;
}
$datea = "01-05-2015";
$date = "01-06-2015";
$hdsarray = array("1-05-2015","2-05-2015","4-05-2015","5-05-2015","7-05-2015","8-05-2015","9-05-2015","11-05-2015","12-05-2015","14-05-2015","15-05-2015","16-05-2015","18-05-2015","19-05-2015","21-05-2015","22-05-2015","23-05-2015","25-05-2015","26-05-2015","28-05-2015","29-05-2015","30-05-2015");
$datesarray = dateRange($datea, $date, $hdsarray);print_r($datesarray);
Result:
Array
(
[0] => 06-05-2015
[1] => 13-05-2015
[2] => 20-05-2015
[3] => 27-05-2015
[4] => 01-06-2015
)
All the 5 dates come in the result, are not sat, sun, and also not there in holidays list.
It seems that there are several problems here. First, as pointed out by others the condition:
if (date('w', $current) != 0){
only checks for Sundays, if it should also include Saturday's it should be:
if (date('w', $current) != 0 && date('w', $current) != 6){
Secondly, it seems that the $hdsarray array does not contain all of the days in May. It seems that all of the Wednesdays are missing.
The third issue is that you are using array_diff on two arrays, one containing Dates and the other ones containing Strings. From the documentation:
Two elements are considered equal if and only if (string) $elem1 ===
(string) $elem2. In words: when the string representation is the same.
In your $hdsarray you are using "1-05-2015" to denote the first day of the month, while:
echo date('d-m-Y', strtotime("1-05-2015"));
results in "01-05-2015". You will need to add an additional 0 in $hdsarray for these dates or work with dates as well.
Last but not least, the current algorithm will not work correctly if the $hdsarray contains dates for a Saturday or Sunday, the result of array_diff will still contain these dates. Since you want to filter the result of daterange the array_filter function might be more suitable.
Despite an answer has already been provided, here is a little snippet with a class handling everything for you:
<?php
class dateRange {
protected $start, $end, $daysToExclude, $datesToExclude;
function __construct($dateStart, $dateEnd, $daysToExclude, $datesToExclude) {
$this->start = $dateStart;
$this->end = $dateEnd;
$this->daysToExclude = $daysToExclude;
$this->datesToExclude = $this->fixFormat($datesToExclude);
}
public function getRangeLength ($callback = null) {
$tmp = array();
$now = strtotime($this->start);
$to = strtotime($this->end);
while ( $now <= $to ) {
if (!in_array(date("w", $now), $this->daysToExclude)) {
$tmp[] = date('d-m-Y', $now);
}
$now = strtotime('+1 day', $now);
}
is_callable($callback) && call_user_func($callback, array_diff($tmp,$this->datesToExclude));
return count(array_diff($tmp,$this->datesToExclude));
}
private function fixFormat($el) {
if (!is_array($el)) {
return false;
}
else {
foreach ($el as &$value) {
$value = date("d-m-Y",strtotime($value));
}
return $el;
}
}
}
?>
I decided to keep your current logic (using date_diff), but I thought that, in the future, you may have your boss telling you "You know what? I don't want to have mondays aswell there" so, with the current system, you will have to edit your function manually and, perhaps, you won't remember anymore what you did.
The class above expects four parameters:
dateStart (d-m-Y format)
dateEnd (d-m-Y format)
daysToExclude (array with IDs of the days to exclude -> example array(0,6) to exclude saturdays and sundays).
datesToExclude (array with the dates to exclude, every format supported).
The class will automatically fix the datesToExclude array format in order to allow you to use date_diff.
Here is an example to use it, following your case:
<?php
$dateStart = "01-05-2015";
$dateEnd = "01-06-2015";
$daysToExclude = array(0,6);
$exclusions = array(
"1-05-2015",
"2-05-2015",
"4-05-2015",
"5-05-2015",
"7-05-2015",
"8-05-2015",
"9-05-2015",
"11-05-2015",
"12-05-2015",
"14-05-2015",
"15-05-2015",
"16-05-2015",
"18-05-2015",
"19-05-2015",
"21-05-2015",
"22-05-2015",
"23-05-2015",
"25-05-2015",
"26-05-2015",
"28-05-2015",
"29-05-2015",
"30-05-2015"
);
$dateRange = new dateRange($dateStart, $dateEnd, $daysToExclude, $exclusions);
echo $dateRange->getRangeLength();
?>
The code above outputs 5.
The function getRangeLength also accepts a callback and will return the array resulting of the date_diff operation, so you can also:
$dateRange->getRangeLength(function($res) {
echo "Literal output: <br />";
print_r($res);
echo "<br />count is: " . count($res);
});
The above outputs:
Literal output:
Array ( [3] => 06-05-2015 [8] => 13-05-2015 [13] => 20-05-2015 [18] => 27-05-2015 [21] => 01-06-2015 )
count is: 5
So if you later will need to remove mondays too, you will be able to easily do that by changing daysToExclude to array(0,1,6);
Hope this will be helpful to anyone else who will need this, despite a valid answer has already been posted.
Your original problem, in any case, was pretty much related to the array_diff function, which was NOT doing its job because of the fact that the date strings were not compatible, because "1-01-2015" is different from "01-01-2015", unless you first convert BOTH of them to times and then back to dates.
The code is fine (except that $nowis not used at all). The problem is the $hdsarray is wrong:
It should $hdsarray = array("01-05-2015", "02-05-2015", "04-05-2015", "05-05-2015", "07-05-2015", "08-05-2015", "09-05-2015",...);
date('d-m-Y', $current);will always return a leading 0 for all days between 1 and 9.
That's where the difference comes from.

Mysql and PHP frequency based on time

I am working on a project to graph frequency over a time period. The server currently stores all the data I need apart from the count as this will change over time. I am pulling all of the data that I need using the following code:
<?php
$con = mysql_connect("127.0.0.1",xxx,xxx);
if (!$con) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("tweets", $con);
$results = array();
$result = mysql_query("SELECT company, time FROM data WHERE company = 'AAPL'");
while($row = mysql_fetch_array($result))
{
$results[] = $row;
}
$results = json_encode($results);
mysql_close($con);
echo $results;
?>
When returned I have an array that contains all of the company names and times. how would I go about counting the frequency within a time frame, for example the frequency in the past 24 hours and then a separate value for the previous 24 hours?
You just loop through the data, the exact code depends on the format of the time and the format of the result required. You could do something like this :
$summary =array();
foreach($results as $result)
{
$day = substring($result['time'], 0, 10);
if(isset($summary[$day])){
$summary[$day]++;
} else {
$summary[$day] = 1;
}
}
Write the function getDay() according to the format of the time.
If your date/time values are stored as MySQL datetime (and for your sake I hope they are) then the solution is trivial. Select records within a certain time period and group by company, e.g.
SELECT
`company`, COUNT(`company`) AS total
FROM
`data`
WHERE
`time` >= now() - INTERVAL 1 DAY
GROUP BY
company
In this example I use MySQL to compute the 24 hour period, but you could just as easily have PHP compute an exact time/date.
If you want a pure PHP solution, then start by storing your times grouped by companies in a multidimensional array. Convert your times from your DB format to Unix time. In my example I use strtotime(); if your db times are in a funky format then you'll need to do something else to convert them.
$result = mysql_query("SELECT company, time FROM data");
while($row = mysql_fetch_array($result)) {
$results[$row['company']] = strtotime($row['time']);
}
Then simply loop the array and evaluate.
// 24 hours before now
$start = time() - ( 24*60*60);
$lastTwentyFourHours = array();
foreach ( $results as $company => $times ) {
if ( !isset($lastTwentyFourHours[$company]) ) {
$lastTwentyFourHours[$company] = 0;
}
foreach ( $times as $time ) {
if ( $time >= $start ) {
$lastTwentyFourHours[$company]++;
}
}
}
print_r($lastTwentyFourHours);

PHP - JSON does not made output

I have written a code that outputs all termins i have the day. The calendar for this is already finished. But the program output, I want to use with python don't work.
My code:
<?php
mysql_connect(deleted);
mysql_select_db("DB1367141")
$day = date("d");
$month = date("m");
$year = date("Y");
$result = mysql_query("SELECT * FROM entries WHERE day = '$day' AND month = '$month' AND year = '$year' ORDER BY hour DESC, minute");
$array = {};
while($obj = mysql_fetch_object($result))
{
if($obj->hour != "--")
$hour = splitf("%02d", $obj->hour);
else
$hour = $obj->hour;
if($obj->minute != "--")
$minute = splitf("%02d", $obj->minute)
else
$minute = $obj->minute;
array_push($array, {"hour":$hour, "minute":$minute, "text":$obj->tex});
}
var_dump($array);
echo json_encode($array);
?>
But if i run it, it neither outputs the array than an "echo('hi');"
I tried out to put this echo at the begin, at the end and in the middle.
But the output is the same: nothing
In another forum I found out that I have to write:
$array = array();
But the output is the same: nothing.
i tryed both, right syntax and error report.
as i changed $array = array(); nothing changed.
i added two lines in my .htaccess to get better error report, and it outputed a 500 Internal Server Error.
Might I recommend you try converting your date storage to timestamps in the name of simplicity. That way you only need to check that the entry is between the first and last second of "today".
You'd save yourself quite a lot of hassle and if you really need to output as in that JSON layout could just parse the timestamp using:
while($obj = mysql_fetch_object($result)) {
$array[] = array(
'hour' => date('H', $obj->timestamp,
'minute' => date('i', $obj->timestamp,
'text' => $obj->tex
);
}
echo json_encode($array);
date('n', strtotime($strTimestamp));
To instantiate a blank array in PHP is
$array = array();
EDIT: as enricog said :)
Also, for simplicity sake, array_push isn't needed, I'd just use:
$array[] = array("hour" => $hour, "minute" => $minute, "text" => $obj->tex);

Codeigniter: Return true if dates are NOT between 2 values

I am using codeigniter to build a rental website for a client. I am trying to return true only if no rental periods match my query. Basically there is a rental table with start date and end date.
My customer selects a start date from a datepicker and the end date is a set number of days after the start date.
So I want to find out if any rental items are being rented on those dates to verify wether the client can reserve the item. Here is what I have so far and I need to accomplish this with Codeigniters active record...
function check_product($periodLength) {
//This is the start time they chose from the picker
$startTime = $_POST['date'];
//The period length is a variable of days, so the end date would be their chosen start date plus a certain amount of days...
$endTime = strtotime('+'.$periodLength.'day', $startTime);
$this->db->where('productsId', $_POST['productId']);
//This is where I need help!!! What query would give me records that are NOT between the start and end dates that i'm wanting
$query = $this->db->get('rentals');
$data = array();
foreach ($query->result() as $row) {
$data[] = array(
'id' => $row->id,
'customerId' => $row->customerId,
'productsId' => $row->productsId,
'periodStart' => $row->periodStart,
'periodEnd' => $row->periodEnd,
'status' => $row->status,
'specialInstructions' => $row->specialInstructions,
'adminNotes' => $row->adminNotes
);
}
return $data;
}
Most of my problem is just in my head i'm sure but i need to figure out if my startdate to enddate period is already reserved.
Try this:
$startTime = $_POST['date'];
$endTime = strtotime('+'.$periodLength.'day', $startTime);
$this->db->where('productsId', $_POST['productId']);
$this->db->where(" $startTime NOT BETWEEN periodStart AND periodEnd AND $endTime NOT BETWEEN periodStart AND periodEnd OR ($startTime < periodStart AND $endTime > periodEnd) ");
//Since this is a complex where clause i would recommend
//to put enitre clause in single where statement rather than
//putting in different where statement.
//And it is upto codeigniter active record standards
$query = $this->db->get('rentals');

How do I calculate the visitors for the last 24 hours?

I have the following code:
$ips = file_get_contents($_SERVER['DOCUMENT_ROOT']."/visitors.txt");
$arr = explode(",",$ips);
$today = strtotime(date('Y-m-d H:i:s'));
for ($n = 0, $max = count($arr); $n <= $max; $n++) {
$visArr = explode("#",$arr[$n]);
$visDate = strtotime($visArr[1]); //$visArr[1] = 2011-12-27 14:10:45
if($visDate < $today){
unset ($arr[$n]); //remove array item if its date not within 24 hours
}
}
The data is stored like this:
xxx.xxx.xxx.xxx#2011-12-27 11:56:24,
xxx.xxx.xxx.xxx#2011-12-28 11:56:24,
I want to get the visitors from the last 24 hours.
I don't want to use MySQL db, I just want to use the txt file but I'm stuck.
Thanks in advance.
I can see 2 problems:
1st you are comparing the stored time with current time and saying that it will filter array item if its date not within 24 hours..
I think you should use $today = strtotime("-1 day");
and name yesterday instead of today..
Secondly and reason of error is that you are exploding data in file with , which will give you "" ie null for last element in array..and thats why strtotime function is giving error for that value..
what you should do is:
if($visArr[1])
{
$visDate = strtotime($visArr[1]); //$visArr[1] = 2011-12-27 14:10:45
if($visDate < $today){
unset ($arr[$n]); //remove array item if its date not within 24 hours
}
}

Categories