I'm building a calendar and I'm really dumb when it comes to arrays.
First of all, I need to query my database, so:
$events = mysql_query ("SELECT id,title,date WHERE date BETWEEN 2009-01-01 AND 2009-01-31")
or die(mysql_error());
So, now I need to order those events so, when I'm echoing my calendar table, I can check this array for events.
In this great Calendar written by David Walsh, he does a query for every day, but I suppose it would be a performance nightmare.
So...any ideas how can I do this?
First up, make sure you're comparing dates with dates. I think your code should be (i.e. with single quotes around date):
$events = mysql_query ("SELECT id,title,date WHERE date
BETWEEN '2009-01-01' AND '2009-01-31' order by date asc")or die(mysql_error());
assuming date is a date column.
i would do that in a elegant for loop
for($i=0;$i<30;$i++)
{
$events[] = mysql_fetch_array(mysql_query ("SELECT id,title,date WHERE date BETWEEN 2009-01-01 AND 2009-01-{$i}"));
}
now you have an array do somethingg with it like this
for($i=0;$i<count($events);$i++)
{
echo $events["id"];
}
will return each id for events in that array
Ok regarding your comments you can do something like this: Get the events like Davek proposed (note the ORDER BY!)
$events = mysql_fetch_assoc(mysql_query ("SELECT id,title,date WHERE date BETWEEN '2009-01-01' AND '2009-01-31' ORDER BY date asc"));
Then you got the events ordered by the date. To output it you can do this:
$last_date = null;
foreach($event in $events) {
if($last_date !== $event['date']) {
echo 'Events for day ' . $event['date'] . ": \n";
$last_date = $event['date'];
}
echo $event['title'] . "\n"
}
Note: This is just a rough sketch, you have to adjust the output of course, but it should give you the right idea.
Output would look like this (in my example):
Events for 2009-01-01:
Event 1
Event 2
Events for 2009-01-02:
Event 1
.
.
.
Edit after comment:
You can write your own function:
function get_events($date, $events) {
$result = array();
foreach($event in $events) {
if($event['date'] == $date) {
$result[] = $event;
}
}
return $result;
}
But this way you search the the complete array over and over again for each day. You can improve it, if you remove the events you already searched for from the $events array. So every time you search in a smaller array. But I would only do this if there is a performance issue.
Related
Hi buddies :) I was required to create a php code to handle some workers' data stored in DB. I got the desired result but it takes seconds and seconds (seconds and seconds! >.<) to finish, so I'm afraid I'm not doing something in a right way :(
The workers' data is stored in a mysql table (table1), something like this:
I'm given a pair of dates: initial_date (a) and final_date (b), so my goal is to copy the given workers' data in a new table (table2), day by day from a to b. The expected table should be as shown below (this table will be used later as a basis for further operations, which is not part of the question)
It's a requirement to overwrite any existing data between a and b dates, and 'jump' weekends and holidays.
To get my goal, I'm coding this (let's assume that the connection and all that is done and the checkworkingday function is given):
$initialdate = '2016-10-10';
$finaldate = '2016-10-12';
$x = $initialdate;
do {
if (checkworkingday($x) == true) {
$query = mysqli_query($connection,"SELECT name,task FROM table1");
while($row = mysqli_fetch_array($query)) {
$task = $row['task'];
$worker = $row['name'];
$query2 = mysqli_query($connection,"SELECT task FROM table2 WHERE name = '$worker' AND date = '$x'");
$row2 = mysqli_fetch_array($query2);
$existingtask = $row2['task'];
if (!isset($existingtask)) {
mysqli_query($connection,"INSERT INTO table2 (date,name,task) VALUES('".$x."','".$worker."','".$task."')");
} else {
mysqli_query($connection,"UPDATE table2 SET task = '".$task."' WHERE date = '".$x."' AND worker = '".$name."'");
}
}
}
$x = date('Y-m-d', strtotime($x . "+1 day"));
} while ($x <= $finaldate);
Just for 3 days as shown in the example, it takes a long to end; and for several weeks or months it takes very, very long (even max execution time is exceeded depending on dates range!).
I'm a newbie and I know the code is quite 'rustic', but I've revised and checked the code and info out there without getting a better performance. What am I doing wrong? Thanks :)
Instead of looping through the enitre data, try INSERT.. SELECT :
INSERT INTO table2 (date,name,task)
SELECT date,name,task
FROM Table1
WHERE < >;
Already solved. I just used WHERE MONTH(due_date) = $month in the SQL clause. Never knew it would just be like that. Thank you for all your answer!
We have a table called bills. We do not delete a bill even if it is paid already for record purposes.
So our goal is to only display The Bills for this Month. I have a $cur_month = current month value. I know how to extract the month value from a field using MONTH(), using a loop to run though the table, but when I try to echo MONTH(date) the value through out the displayed series is just the MONTH VALUE of the very first row. It seems it failed to get the MONTH VALUE of the other rows.
Fixed code below
$query = "SELECT * FROM bill WHERE MONTH(due_date)=$month";
$bresult = mysql_query($query);
while($brow = mysql_fetch_array($bresult, MYSQL_ASSOC))
{
$bdata = mysql_fetch_assoc(mysql_query("SELECT MONTH(due_date) AS M FROM `bill`"));
if($bdata['M'] == $month)
{
echo "<tr>";
echo "<td>".$brow['room_id']."</td>";
echo "<td>".$brow['tenant_id']."</td>";
echo "<td>".$brow['due_date']."</td>";
echo "</tr>";
}
}
$month there is the holder of the current month
$bdata['M'] there is the holder of the month extracted. We just displayed it to check.
So if extracted_month is equls to current_month then display bill
I hope you can help me in this.
PS: Still an amateur. This is not yet an online website. We only need help for the purpose of having it work.
1) Use a WHERE statement in your first SQL to only fetch those rows from the table.
Like this:
$query = "SELECT *, MONTH(due_date) as M FROM bill WHERE MONTH(due_date)=" . $month;
$bresult = mysql_query($query);
while($brow = mysql_fetch_array($bresult, MYSQL_ASSOC)) {
echo "<tr>";
echo "<td>".$brow['M']."</td>";
echo "<td>".$brow['tenant_id']."</td>";
echo "<td>".$brow['due_date']."</td>";
echo "</tr>";
}
2) I find it good practice to always check if the result object is created and if so, to check if it returned matches (with mysql_num_rows($result)). That way you can show an error if something goes wrong (most likely in the SQL statement) or show the user that there are no matches (bills in this case).
3) Try to use MYSQLI to connect to your database instead of MYSQL, since the latter is deprecated. (See: http://php.net/manual/en/mysqli-result.fetch-assoc.php for an example.)
Try solving this problem using SQL.
SELECT b.amount_paid
FROM bills b
WHERE MONTH(b.due_date) = 3
Using the result of this query you would have all of the amounts for this month. Sum your result and you are done.
I can't figure out how to isolate only the Date variable in an array that is pulling all of the keys from MYSQL. I want to make it format %M %d. How can I pull it out of $dataFields array modify it then put it back in? The Key is "Date".
include('include/connect.php');
$table='currentJobs';
$sql="SELECT * FROM `".$table."`";
$result=mysql_query($sql,$dbLink);
$data=array();
$d=0;
while($row=mysql_fetch_assoc($result)){
$dataFields=array();
while(list($key,$value)=each($row)){
$dataFields[]='<td class="'.$key.'" >'.$row[$key].'</td>';
if ($d==0){
$dataKeys[]='<th class="'.$key.'" >'.$key.'</th>';
}
}
if ($d==0){
$data[$d]='<tr>'.join('',$dataKeys).'<th class="actions">Actions</th></tr>';
$d++;
}
$data[$d]='<tr>'.join('',$dataFields).'<td>
Update</td></tr>';
$d++;
}
mysql_free_result($result);
if ($d>0){
echo '<table class="sortable">'.join('',$data).'</table>';
}
else {
echo 'Sorry, data was not found';
}
mysql_close($dbLink);
It is currently Displaying:
Date Name Phone Bike_Year Bike_Model Current_Status Service_Type ▴ Mechanic Revenue Notes Actions
0000-00-00 Test User 206-555-5555 2001 FLHRI Checked In Spec Service Interval Johhny 840.30 Update
$sql="SELECT
date_format(date, '%M %d') AS date,
Name,Phone,Bike_Year,Bike_Model,Current_Status Service_Type,Mechanic,Revenue,Notes
FROM `".$table."`";
This method is less efficient then just modifying the format within the SQL as suggested by JOE LEE. But either way works, whichever you prefer should work.
if($key == 'Date'){
$dataFields[]='<td class="'.$key.'" >'.date('M d',strtotime($row[$key])).'</td>';
} else {
$dataFields[]='<td class="'.$key.'" >'.$row[$key].'</td>';
}
or compact:
$dataFields[] = $key == 'Date' ? date('M d',strtotime($row[$key])) : $row[$key];
Look here for the date format options:
http://us1.php.net/manual/en/function.date.php
I am building a website where users can reserve appointments.
I am currently building a javascript app for the project, where user can pick a date from a calendar and see the available appointments. When I am building the calendar, I need to color dates by available appointments (ex. green if there's any).
In order to do that I need to iterate a javascript array that contains all available reservations. At the moment it looks something like this:
[Object, Object, Object...]
Where the object is a javascript object that contains appointment info. Here is the php service that serves the JSON:
<?php
require_once('../include/dbconnect.php');
$sql = "SELECT appointment.example,...
person.example,...
FROM appointment, person
WHERE appointment.reserved=0";
$stmt = $db->prepare($sql);
$stmt->execute();
$array = array();
while($row = $stmt->fetchObject()){
array_push($array, $row);
}
echo json_encode($array);
?>
So this finally brings us to the question.
For easier javascript array scanning, I'd need an array/object includes appointments arranged/sorted by date. Then when I am creating an element that represents the date, I can check the object for matching data. Data like this:
{
15.09.2012 : Object,
16.09.2012 : Object{
appointment1 : Object,
appointment2 : Object
}
}
In the database an appointment has an attribute "date" which is currently a string like "16.09.2012". Should I also change it to unix timestamp?
How should I change the PHP service to output a JSON object that includes appointments filed under dates?
A possible solution is to use associative arrays in php :
$assoc = array("key" => "value");
When you fetch your database records you can do something like this :
$array = array();
while($row = $stmt->fetchObject()){
$array[$row -> date] = $row;
}
echo json_encode($array);
For sorting, you can use the ksort ( http://php.net/manual/en/function.ksort.php ) php function, to sort the array by key.
Now you will have a Javascript Object and not Javascript array.
Now you can iterate the object with for .. in javascript loop ( How to Loop through plain JavaScript object with objects as members? )
You can give try as below:
$sql = "SELECT appointment.example,...
person.example,...
FROM appointment, person
WHERE appointment.reserved=0 ORDER BY appointment.date_field ASC";
$stmt = $db->prepare($sql);
$stmt->execute();
$array = array();
while($row = $stmt->fetchObject()){
$array[$row->date_field][]=$row;
array_push($array, $row);
}
echo json_encode($array);
?>
You don't need to construct an object consisting of date keys. Instead:
include the dates in your current structure and sort the array by date:
<?php
require_once('../include/dbconnect.php');
$stmt = $db->query('
SELECT DATE(appointment.datetime) AS date,
appointment.datetime,
appointment.reserved,
appointment.example, -- do you really want to send sensitive
person.example -- data about appointments to the browser?
FROM appointment JOIN person ON ...
WHERE appointment.reserved = 0 -- should this be = 1?
ORDER BY appointment.datetime
');
echo json_encode($stmt->fetchAll(PDO::FETCH_OBJ));
?>
then skip over matching days when progressing through the array:
// loop over all dates displayed in calendar
for (
currentDate = startDate, i = 0;
currentDate <= endDate;
currentDate.setDate(currentDate.getDate() + 1)
){
// determine whether the current date is booked
// and advance pointer to next date in array
for (
booked = false;
i < arr.length && arr[i].date == currentDate;
++i
) booked |= arr[i].reserved; // or just `booked = true` if query
// returned only booked appointments
// apply appropriate CSS to currentDate
// ...
}
You might even consider reducing the client-side overhead by first returning a JSON array only of booked dates (in which case the inner loop above could be replaced with a simple if statement):
SELECT DISTINCT DATE(appointment.datetime) AS date
FROM appointment JOIN person ON ...
WHERE appointment.reserved = 0 -- should this be = 1?
ORDER BY date
And then, once the user selects a date, make a further query for the bookings on that date:
SELECT appointment.datetime
FROM appointment JOIN person ON ...
WHERE appointment.reserved = 0 -- should this be = 1?
AND DATE(appointment.datetime) = ?
ORDER BY appointment.datetime
I have these mysql dates in a table of my database,
2010-07-16 20:09:06
2010-08-16 20:19:43
2010-10-18 16:57:19
2009-09-18 16:57:42
2009-10-18 16:57:55
2009-12-24 14:59:21
How can I sort them into the result below so that I can have the end user browses monthly results?
<h2>2010</h2>
<ul>
<li>October</li>
<li>November</li>
<li>December</li>
</ul>
<h2>2009</h2>
<ul>
<li>September</li>
<li>October</li>
<li>November</li>
<li>December</li>
</ul>
can't think of anything!
I usually use gmdate() to format the dates from mysql database, for instance,
<?php
$sql = "
SELECT *
FROM root_pages
WHERE root_pages.pg_hide != '1'
ORDER BY pg_created DESC";
#instantiate the object of __database class
$object_items = new __database(DB_HOST,DB_USER,DB_PASS,DB_NAME);
$items = $object_items -> fetch_all($sql);
echo gmdate('j/n/Y', strtotime($item['pg_created']));
?>
it would great if you can give me some hint to start!
thanks,
Lau
There's plenty of ways to do this... Using MySQL, you could
SELECT DISTINCT YEAR(dt) y, MONTH(dt) m FROM t ORDER BY dt DESC
Then loop through the results:
$year = null;
foreach ($rows as $row)
{
if ($year != $row->y)
{
if ($year) echo "</ul>";
$year = $row->y;
echo "<h2>$year</h2>\n";
echo "<ul>\n";
}
echo "<li><a href='#'>{$month_name[$row->m]}</a></li>\n";
}
if ($year) echo "</ul>";
It assumes there is an array called $month_name that maps a month number to its name.
This method is most useful if you don't need the other data for that page. If you do need the full data, then you can drop the DISTINCT from the SQL, SELECT all the field you need, and add a variable to track the current $month throughout the iteration, as the above code does with $year.
Assume date is the date column you're interested in.
SELECT DATE_FORMAT(`date`, '%m-%Y') AS `formatted_date`
FROM `pages`
GROUP BY `formatted_date`
ORDER BY `date`
08-2010
09-2010
11-2010
12-2010
02-2011
03-2011
This gives you all the months that have pages. It should be simple enough to output this in some HTML. Some functions that may help along the way: explode, mktime, strtotime, date.
You can use my trick:
1
get all the info out of mysql as-is using some of the others comment's good advice.
2
make an array using strtotime:
<php? $r=array((int)strtotime('2010-07-16')=>'2010-07-16 20:09:06',) ?>
3
--sort it using
ksort($r,SORT_NUMERIC) or krsort,
Have fun with php sorting functions. http://www.php.net/manual/en/function.sort.php
Note. the only down fall to this approach is that in a 32 bit machine the numeric values have limits and numbers higher than (int)2147483647 have to be cast as (strings) or (float) to be used as array keys.
You can us a dot (string)'2147483647.'