Reputation:
I have a task that I've been racking my head around all day no avail. I have a MySQL table that's set up as follows:
CREATE TABLE `Shows` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`band` varchar(255) NOT NULL,
`month` int(2) NOT NULL,
`day` int(2) NOT NULL,
`year` int(4) NOT NULL,
`venue` varchar(255) NOT NULL DEFAULT '',
`city` varchar(255) NOT NULL DEFAULT '',
`state` varchar(2) NOT NULL DEFAULT '',
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)
Basically, it's a table to hold information about concerts. The month and day are stored numerically without leading zeros (e.g. February 3 would be represented as 2 in the month column and 3 in the day column).
I'm creating an events calendar page that displays information about upcoming concerts. I want to set it up so that it loops through each day that's equal to or after the current date so that no previous concerts show up on events that are supposed to be upcoming.
Here's the code I have so far:
function displayUpcomingShows()
{
include "/path/to/config/file/that/contains/credentials";
$con = mysql_connect($credentials);
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("database", $con);
$dateQuery = mysql_query("SELECT * FROM Shows GROUP BY month, day, year") or die(mysql_error());
$todayMonth = date(n);
$todayDate = date(j);
$todayYear = date(Y);
while ($info = mysql_fetch_array($dateQuery))
{
if ($todayMonth <= $info['month'] && $todayDate <= $info['day'] && $todayYear <= $info['year'])
{
$showDate = date("F j, Y", mktime(0, 0, 0, $info['month'], $info['day'], $info['year']));
echo "<b><li>$showDate</li></b>";
$concertDetails = $info['band'] . " @ " . $info['venue'] . " in " . $info['city'] . ", " . $info['state'];
echo "<li>$concertDetails</li>";
}
}
mysql_close($con);
}
This code works perfectly if there are 2 different dates. That is, if the rows inserted into the table look like this:
INSERT INTO `Shows` (`id`, `band`, `month`, `day`, `year`, `venue`, `city`, `state`, `timestamp`)
VALUES
(1,'Some Band',12,8,2011,'The Crocodile Cafe','Seattle','WA','2011-12-07 22:50:06'),
(2,'Some Other Band',12,15,2011,'Nectar Lounge','Seattle','WA','2011-12-07 15:17:39');
The web page displays:
December 8, 2011
Some Band @ The Crocodile Cafe in Seattle, WA
December 15, 2011
Some Other Band @ Nectar Lounge in Seattle, WA
Perfect, exactly what I wanted. BUT, if I change the first row so that the show is on the 15th as well, like so:
(1,'Some Band',12,15,2011,'The Crocodile Cafe','Seattle','WA','2011-12-07 22:50:06')
The web page only prints this first entry and doesn't display the second entry (Some Other Band) at all, like this:
December 15, 2011
Some Band @ The Crocodile Cafe in Seattle, WA
Can somebody point me in the right direction or explain what I'm doing wrong? I've also tried structuring my query so that it selects the distinct dates only, loops through those using the same while loop and if statement in the code above, but then contains a new query inside the if statement that selects all information from the table where the month, day, and year match, then uses another while loops to print that data, but this causes the page to stop loading right when the function is called. That code looks like this:
function displayUpcomingShows()
{
(...same code as above up until here...)
$dateQuery = mysql_query("SELECT DISTINCT month, day, year FROM Shows") or die(mysql_error());
$todayMonth = date(n);
$todayDate = date(j);
$todayYear = date(Y);
while ($info = mysql_fetch_array($dateQuery))
{
if ($todayMonth <= $info['month'] && $todayDate <= $info['day'] && $todayYear <= $info['year'])
{
$showDate = date("F j, Y", mktime(0, 0, 0, $info['month'], $info['day'], $info['year']));
echo "<b><li>$showDate</li></b>";
$detailsQuery = mysql_query("SELECT * FROM Shows WHERE month = $info['month'] AND day = $info['day'] AND year = $info['year']") or die(mysql_error());
while ($concertInfo = mysql_fetch_array($detailsQuery)
{
$concertDetails = $concerinfo['band'] . " @ " . $concertInfo['venue'] . " in " . $concertInfo['city'] . ", " . $concertInfo['state'];
echo "<li>$concertDetails</li>";
}
}
}
mysql_close($con);
}
Sorry if this particularly verbose, but I wanted to make sure I was as detailed as possible. I'm making decent progress with learning PHP/MySQL more fluently, but I suppose that's why I'm still struggling.
Cheers for any help.
Upvotes: 3
Views: 2568
Reputation: 58534
MySQL knows what day it is (CURRENT_DATE), so you can just ask the database for future shows without your code looking up today's date. You can also ask it to format the date for you:
-- I prefer ANSI_QUOTES: using "identifier" vs. `identifier`
-- and PIPES_AS_CONCAT: a || b || c vs. CONCAT(a, b, c)
SET sql_mode='ANSI';
SELECT STR_TO_DATE("year"||','||"month"||','||"day", '%Y,%m,%d') AS showdate,
band,
venue,
city,
state
FROM Shows
WHERE "year" >= YEAR(CURRENT_DATE)
AND
"month" >= MONTH(CURRENT_DATE)
AND
"day" >= DAY(CURRENT_DATE);
Note that that query would be easier if you collapsed the broken-out date fields into a single column:
...
"showdate" DATE NOT NULL,
...
Then you could simply SELECT showdate, ... FROM Shows WHERE showdate >= CURRENT_DATE
Upvotes: 0
Reputation: 990
The problem is with you select query
SELECT * FROM Shows GROUP BY month, day, year
The GROUP BY is causing the problem. Your basically asking the database to consolidate the data. The query sees two records but they are on the same day. You asked to group records by day, so it won't show two records in a row that are on the same day. Same thing happens with month and year. I think what you what to do is ORDER BY.
You really should use something like phpMyAdmin to run your queries and get the bugs worked out before sticking it in your code.
Upvotes: 0
Reputation: 31813
you have a parse error here
$detailsQuery = mysql_query("SELECT * FROM Shows WHERE month = $info['month'] AND day = $info['day'] AND year = $info['year']") or die(mysql_error());
it would need to be
$detailsQuery = mysql_query("SELECT * FROM Shows WHERE month = {$info['month']} AND day = {$info['day']} AND year = {$info['year']}") or die(mysql_error());
There's a lot of info on string if you want, although it might be hard to digest http://www.php.net/manual/en/language.types.string.php the examples should be a good reference though.
do yourself a favor and turn on error reporting so php will tell you stuff like that. find your php.ini and make sure
display_errors = on
error_reporting = E_ALL
then restart the webserver to make sure changes take effect
trying to code without being able to see detailed error messages is hellish.
Upvotes: 0
Reputation: 5701
Easy update your query like so:
mysql_query("SELECT * FROM Shows WHERE timestamp >= '".date('Y-m-d H:i:s').'") or die(mysql_error());
Get rid of:
$todayMonth = date(n); $todayDate = date(j); $todayYear = date(Y);
And in your while loop get rid of the IF statement all together
So your code will look like:
function displayUpcomingShows()
{
include "/path/to/config/file/that/contains/credentials";
$con = mysql_connect($credentials);
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("database", $con);
$dateQuery = mysql_query("SELECT * FROM Shows WHERE timestamp >= '".date('Y-m-d H:i:s')."'") or die(mysql_error());
while ($info = mysql_fetch_array($dateQuery))
{
$showDate = date("F j, Y", mktime(0, 0, 0, $info['month'], $info['day'], $info['year']));
echo "<b><li>$showDate</li></b>";
$concertDetails = $info['band'] . " @ " . $info['venue'] . " in " . $info['city'] . ", " . $info['state'];
echo "<li>$concertDetails</li>";
}
mysql_close($con);
}
Upvotes: 2