Jump to content

creating a monthly calendar (advice - begginner)


Recommended Posts

Hi,

I am planning on writing a script that dynamically creates a calendar, that will be displayed like this:
http://www.area52.com.au/calendar/current.htm

I haven't got any real experience with php, though I have done some OOP with Java. This will take me a while to develop as I am learning as I go :D
I would like to write the script using flat files, as I dont know anything about databases either, and I think learning one thing at a time will be quite enough :D

The data for each event to be displayed will be entered via a form, then stored in a directory for the month that it falls in. When the calendar script is run, it will use the date function to display all events happening in that particular month (with a header specifying the month), devided by each week (mon to sun), and then the events in order mon to sun.

So what I am thinking is that the form to enter an event will then be turned into a string of HTML code, styled with CSS, so each event can simply be a string of info converted to HTML code when it is submitted. (as in, they enter "event name" but on submission I enclose it in the appropriate div class tags for styling etc)

I am thinking of saving the files with the file name to be the date of the event - say the day first.
Use the date function to get the current month, then use scandir() to put the files in an array that are in that months directory.
Do something to create the headers of each week with the date function, then a loop to go through the array, echoing the files that fall with day dates in that week.

This way there can be links to preceeding and following months that will run in the same way allowing users to see whats happening in the future or happened before. I can periodically clean out old directories after 6 months or a year.

So my question is, is this an inefficient way to go about writing the script? will it take a long time to run? It will have to traverse the array about four or five times to display the whole month, or I could use a loop to only read the files with the days in that week. I am thinking of using file_get_contents() to read the data in the file to put it all into a string to echo.

Any thoughts or comments? more technical questions will come when I start to write the script, but I need to have the method I am going to use in my mind before I start to write anything.

Another method i thought of was using linked classes, like a class for event, class for week, and class for month, but I dont think I need to do that if I can store and retrieve the files properly?

Cheers!
I am starting on an algorithm outline that may make it easier to understand what Ia m saying I want to do:

Algorith outline:
// files of events will be named eg: 15-1-01 (ie 15th of the first, first file of that day). When there is another event falling on the same day it will be named 15-1-02
get current date

//assign variables for use in this month

variable $currentMonth becomes the name of this month(eg: January)
variable $week1Mon becomes formatted date (eg: Monday 2nd January)
variable $week1Sun becomes formatted date (eg: Sunday 8th January)
variable $week2Mon becomes formatted date (eg: Monday 9th January)
variable $week2Sun becomes formatted date (eg: Sunday 15th January)
variable $week3Mon becomes formatted date (eg: Monday 16th January)
variable $week3Sun becomes formatted date (eg: Sunday 22nd January)
variable $week4Mon becomes formatted date (eg: Monday 28th January)
variable $week4Sun becomes formatted date (eg: Sunday 3rd February)
variable $eventFiles becomes array scandir($currentMonth)

//start organising and displaying the page

Display "Special events for $currentMonth"

Display "$week1Mon to $week1Sun"

Display all events in array from week start date to week end date.
maybe:
a counter to keep track of which day we are processing, starts at start of month date (ie 01).
$endWeekDate becomes int equal to the last date in the week (have to research methods)
while (counter < $endWeekDate +1)
display 1st file with first two numbers of file name equal to counter
while (next file has same two numbers at start of file name (ie their on the same day) then display those too.
once events for that day are displayed, then counter increments.
so this loop will go untill the end of the week

Display "$week2Mon to $week2Sun"

then do the same loop as before, probably best to put it in a method called displayWeek(), untill we hit the last end date of the month.

any OOP i have done before I have issues with flow of control, and algorithm design, but I thought I'd put this up to give people an idea of the kind of thing the code might be doing from what I explained above.

thoughts? suggestions for improvement, or any kind of built in methods that might help?

Cheers
Well let me just say that OOP in php is much easier then with Java so you should be right at home. Now as far as using flat files over mysql, I would have to disagree with that being easier. Sql is really pretty simple and if you know Java you should be able to get Sql down in no time, or at least enough for a project like this.

Now on to the reason for my post. Calendars can be a bit tricky so I thought I would post a simple working calendar as an example. You should be able to use this as a general reference. By the way, no oop in this one..

[code]
<?php
    $now = getdate(time());
    $time = mktime(0,0,0, $now['mon'], 1, $now['year']);
    $date = getdate($time);
    $dayTotal = cal_days_in_month(0, $date['mon'], $date['year']);
    //Print the calendar header with the month name.
    print '<table>
        <tr>
<td colspan="7"><strong>' . $date['month'] . '</strong></td>
</tr>';
    for ($i = 0; $i < 6; $i++) {
        print '<tr>';
        for ($j = 1; $j <= 7; $j++) {
            $dayNum = $j + $i*7 - $date['wday'];
            //Print a cell with the day number in it.  If it is today, highlight it.
            print '<td';
            if ($dayNum > 0 && $dayNum <= $dayTotal) {
                print ($dayNum == $now['mday']) ? ' style="background: #ccc;">' : '>';
                print $dayNum;
            }
            else {
                //Print a blank cell if no date falls on that day, but the row is unfinished.
                print '>';
            }
            print '</td>';
        }
        print '</tr>';
        if ($dayNum >= $dayTotal && $i != 6)
            break;
    }
    print '</table>';
?>
[/code]

As you can see this is really basic and will only display one month at a time but it may help some.
Thanks for your advice tomfmason, that definately gives me something to play around with to get familiar with the methods that should be used to manipulate date data.

The more I think about it though, I wonder if I am approaching this the wrong way. If you look at the example link (which I want the dynamically generated one to look like), all it really is is a list of events, and they happen to be sorted by date. It would also be useful (as these are gaming events of various kinds) to sort the list by showing just game genres, or specific games.

So if I think about it as a dynamically generated list, then I would go the way of creating an object for each event. Then, when generated would show list by date (descending) by default.

So each object (event) has a date, a game type, a title, a time and information. I could then use a conditional statement to insert objects that have a date that coincides with the week it should be in, if the date doesn't fit, then it doesn't go in until the right week comes up. Then I am able to minimise the amount of date functions I need to use, and just use them to specify the month at the top of the page, and the weeks of the month. this would make it easy to sort the list by game type etc.

Does this sound more sensible than creating an actual calendar, as I dont want days displayed if they have no events (as the events most often happen on the weekends anyway, and rarely during the week)

I'll start writing out a draft of an algorithm (that makes more sense than the previous one) and see how we go. Thoughts?
I agree with tomfmason, if you have a little programming experience, then simple mysql should be no problem for you. I have no other experience in programming aside from php & mysql. The PHP was a bit tricky at first (still is at times) but mysql was pretty easy to pick up on. Pretty "simple" when you see it in action.

What you are wanting to do sounds like a pretty straightforward store / retrieve / sort  of data. I think MySql would be MUCH better suited (and easier) than trying to use a flat file db.

I tried storing and retrieving data from flat files, and it was a disaster. I have found MySql much easier to deal with.

Grab a good book on php mysql and have at it. The first book I read was called "How to Do Everything with PHP & Mysql" by Vikram Vaswani. It is a great book that gets right to it without all the bloated commentary and the examples he provides work right the first time.

Good luck in your endeavor, and keep plugging away line by line (I sound like a coke dealer  ;D ) and before you know it, this project will seem like a cake walk

nate
ok, thanks very much for your advice guys :D

I'll go and check out SQL then, we have one spare available database, so i may as well use it. You guys would know better than me wether it is more efficient to create a DB or to do flat files so thanks for that. Probably saved me a giant headache!

I might revive this topic for technical questions when I start writing the php code.

Cheers!
  • 2 weeks later...
ok, i discovered the sql query's werent too hard :D by chopping up the example calendar given above, and utilising a week range finding method from php builder forums, I managed to come up with just what I wanted! :D

I started adding a bit of functionality to it, which is where it got broken, numerous times, but I managed to fix it mostly. As I kept adding things it makes me wonder if there is a more streamlined way to create the function, or break it up more.

The database table has columns for event name, authorised (0 or 1), week number, timestamp, id, info, link, and more text fields for information

basically by default the script gets the current date, then figures out how many weeks it needs to display. for each week it goes through and gets all entries that are authorised, have a corresponding week number and displays them by earliest date in the week to the latest. The method to find the week range of dates is used to create the week headers.

I added the sorting method on the left hand side, so that the events can be sorted by last or next month too, and also so that the calendar can display just a certain game. then it broke, sort of, where it will not display events untill the results are sorted with the form, though it does go through and get all the week headers. I'm pretty sure its got something to do with this where the query is created, and obviously something to do with the sorting form, and I get the feeling its relatively simple, but after banging my head on this and squeezing so much into my brain it is a blur :D

any ideas, or comments on the code below?

[code]
<!-- InstanceBeginEditable name="PageContent" -->
  <div id="sideNav">
  <div class="module_heading">
  Monthly Events </div>
<div class="sortBox">
<span class="bold">Sort by month or game</span>
  <form method='POST' action='calendar.php' name='calendarSort'>
  <select class="sortbox" name='sortMonth'>
          <option value='current'>Current Month</option>
          <option value='last'>Last Month</option>
          <option value='next'>Next Month</option>
        </select>
  <select class="sortBox" name='sortGame'>
          <option value='all'>All</option>
  <option value='Area 52'>Area 52</option>
          <option value='Confrontation'>Confrontation</option>
          <option value='D&D'>Dungeon and Dragons</option>
          <option value='FOW'>Flames of War</option>
          <option value='GW'>Games Workshop</option>
          <option value='L5R'>Legend Of The Five Rings</option>
          <option value='Magic'>Magic: The Gathering</option>
          <option value="Pokemon">Pokemon</option>
          <option value="SG">Sabertooth Games</option>
          <option value="V:TES">Vampire: The Eternal Struggle</option>
          <option value="WOW">World Of Warcraft</option>
          <option value="Yugioh">Yu-Gi-Oh</option>
          <option value="Other">Other Games</option>
        </select>
<input type='submit' value='Sort Events' name='butSubmit' />
  </form>
  </div>
  <div id="sideNavFooter">   </div>
  <div class="module_heading">
  Constant Events </div>
  <div class="moduleTextOnly"><span class="bold">Wednesdays and Thursdays</span><br />
  blah blah removed some html paragraphs here<br />
</div>
 
  <div id="sideNavFooter">   </div>
  </div>
<div id="content">
<?php

// set variables:
include("include/config.php");
$now = getdate();// get array of current date
$monthNum = date('m');// get the month number to give to the display calendar function

//see if we are sorting by month
if ($_POST['sortMonth'] == 'last')
{
$monthNum = $monthNum-1;
}
if ($_POST['sortMonth'] == 'next')
{
$monthNum++;
}

// open connection
$connect = mysql_connect($host, $account, $login) or die ("Unable to connect!");

// select database
$db = mysql_select_db("area52co_phpbb2", $connect) or die ("Unable to select database!");

//display calendar of chosen month
displayCalendar($monthNum, $now['year']);

function displayCalendar($month, $yearNum)
{
$dayTotal = cal_days_in_month(0, $month, $yearNum);//get total days for month specified in parameters
$weekRange = $dayTotal / 7;// generate the amount of weeks we want to show in this months calendar (includes enough to oveerlap into following month)
$firstWeekNum = date('W', mktime(0, 0, 0, $month, 1, $yearNum));//find the week number we want to start showing the calendar at by getting the date for the 1st of the month specified
$weekNum = $firstWeekNum;//set the weeknum variable initially to the week we want to start at, weeknum increments at the end of each week displayed
$monthName = date('F', mktime(0, 0, 0, $month, 1, $yearNum));//get the name of the month to feed into the SQL query

//Display month header
echo '<div class="subHeading">Calendar of events for '.date('F Y', mktime(0,0,0,$month,01,$yearNum)).'</div>';
echo '<div class="textCenter">All events take place at Area 52 unless otherwise specified.</div>';
//Loop displays all events in the database grouped by weeks, loop goes for as many times equal to the amount of weeks we need to show for a given month
for ($i =0; $i <= $weekRange; $i++)
{
// create query
$query = "SELECT * FROM calendar_events WHERE month='".$monthName."' AND week=".$weekNum." AND auth=1 ";

//see if there are any more conditions of sorting to add to the query
$game = 'all';
$game = $_POST['sortGame'];

if (!($game == 'all'))
{
$query = $query."AND game='".$game."' ORDER BY time ASC;";
}
else
{
$query = $query."ORDER BY time ASC;";
}

// execute query
$result = mysql_query($query) or die ("Error in query: $query. ".mysql_error());

//create week header
$desiredMonday = StartOfWeek($yearNum, $weekNum);//get a timestamp of the monday of the week we are up to
$weekMon = date('l jS \of F', $desiredMonday);//format the date of the monday into something friendly
$weekSun = date('l jS \of F', strtotime('+ 6 days', $desiredMonday));//calculate the days untill the sunday of that week and format that one too
//print week header
echo '<div class="weekHeader">'.$weekMon.' to '.$weekSun.'</div>';

// see if any rows were returned
if (mysql_num_rows($result) > 0)
{
// yes
// print them one after another
while($row = mysql_fetch_row($result))
{
echo '<table class="calendarEntry">
<tr>
<td colspan="2"><div class="bold">'.$row[6].' :: '.$row[5].'</div></td>
</tr>
<tr>
<td><p>'.$row[7].'</p><br />';
$link = $row[8];
echo 'this is link:<br />'.$link;
echo strlen($row[8]);
if (strlen($row[8]) == 0)
{
echo '<a href="http://'.$row[8].'>Click here for more information</a>"';
}
echo '</td>
<td class="calDetails"><span class="bold">When: </span>'.date('l j/M H:i', $row[1]).'<br />
<span class="bold">Contact:</span> <a href=mailto:'.$row[10].'>'.$row[9].'</a><br />
<span class="bold">Cost: </span> $'.$row[11].'</td>
</tr>
</table>';
}
}else {
// no
// print status message
echo "No events for week found! <br />";
}
$weekNum++;
}
}


// Method to get the range of the week to put in the header week for each display
//thanks to weedpacket from www.phpbuilder.com
function StartOfWeek($year, $week)
{
    $Jan1 = mktime(1,1,1,1,1,$year);
    $MondayOffset = (11-date('w',$Jan1))%7-3;
    $desiredMonday = strtotime(($week-1).' weeks '.$MondayOffset.' days', $Jan1);
    return $desiredMonday;
}

// free result set memory
//mysql_free_result($result);

// close connection
mysql_close($connect);

?>
</div>
[/code]
  • 2 weeks later...

I think I am having a problem with this portion of the code:

 

// create query 
$query = "SELECT * FROM calendar_events WHERE month='".$monthName."' AND week=".$weekNum." AND auth=1 "; 

//see if there are any more conditions of sorting to add to the query
$game = 'all';
$game = $_POST['sortGame'];

if (!($game == 'all'))
{
	$query = $query."AND game='".$game."' ORDER BY time ASC;";
}
else
{
	$query = $query."ORDER BY time ASC;";
}

 

or it might be this part, that runs when the the submit button is clicked:

<form method='POST' action='calendar.php' name='calendarSort'>

 

Would this reset the form values? The month one seems to work fine, (outlined in the code above this post), but when I am trying to sort by game it does not work. For this to work, I need to pass three AND statements to the query, is this too many? do I need to enclose them in brackets?

 

I am echoing the query into the page each time it is executed, just to see what the query ends up being, and the AND game=gamename never makes an appearance.

 

Any ideas? The link to the page is here, if you want to see what I mean. It also shows that no events are shown untill you press the sort button (with the default options picked) but thats another problem.....

 

http://www.area52.com.au/calendar/dynamicCalendar/calendar.php

This may throw a wrench in things for ya, but I seriously recommend using unix timestamps for storing your date. with timestamps, you store 1 string such as..1172037600

 

From that string you can do date searching and manipulation fairly easy.

 

<?php
$time_string='1172037994';

echo date("h:i:s A m/d/Y",$time_string);
?>

 

gives you

 

12:06:34 AM 02/21/2007

 

You can do things like

$query = "SELECT * FROM calendar_events WHERE date between '$date1' and '$date2' AND auth=1 ";

 

or

 

$query = "SELECT * FROM calendar_events WHERE date < '$date' AND auth=1 "

;

Just my 2 cents

I record a unix timestamp with every entry, because to begin with I thought I'd be able to use it to do anything I needed with the date (as you say)

 

I thought it might be easier to store the month name as a string and the week number in the row aswell, because these are really the two things I need the most (though the timestamp does help in allowing me to sort it from earliest to latest in any given week.) I thought trying to use the timestamp to make the query's might make the code convoluted, or even harder for me to understand what I was doing.

 

I like the sound of that "WHERE date between '$date1' and '$date2'"

didn't realise you could do that! my SQL knowledge certainly leaves a lot to be desired so far as finding the most efficient ways of doing things goes, but I also have to learn it at uni this semester, so that should kick me in the bum or help a bit.

 

So to use that, I get a timestamp of the start of the week, a timestamp for the end of the week, then feed those into the query (instead of using my month and weeknums) for each iteration of the loop to make the weeks.... hmmmm.....

 

(lol, looking at the code posted I am seeing so many silly logic errors in my php.... ::))

 

Thanks, all these little comments fire me off on tangents that are helping me get my head around this :D

 

Cheers!

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.