Tải bản đầy đủ (.pdf) (10 trang)

Tương tác giữa PHP và jQuery - part 14 potx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (376 KB, 10 trang )

CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

131
}

?>
■ Note That the Calendar class constructor accepts an optional $dbo argument that is passed in turn to the
DB_Connect constructor. This allows you to create a database object and pass it for use in the class easily.
Creating a File to Store Database Credentials
To keep the database credentials separate from the rest of the application for easy maintenance, you
want to use a configuration file. Create a new file called db-cred.inc.php in the config folder
(/sys/config/db-cred.inc.php). Inside, create an array called $C (for constants), and store each piece of
data as a new key-value pair:

<?php

/*
* Create an empty array to store constants
*/
$C = array();

/*
* The database host URL
*/
$C['DB_HOST'] = 'localhost';

/*
* The database username
*/
$C['DB_USER'] = 'root';


/*
* The database password
*/
$C['DB_PASS'] = '';

/*
* The name of the database to work with
*/
$C['DB_NAME'] = 'php-jquery_example';

?>
CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

132
■ Note Initializing $C as an empty array is a safeguard against any tainted pieces of data being stored in $C and
defined as constants. This is a good habit, especially when dealing with sensitive data.
Save this file. If you’re not using XAMPP or if you’ve modified the default database credentials, you’ll
need to substitute your own host, username, password, and database name in the code.
Creating an Initialization File
At this point, your database credentials still aren’t stored as constants. You’ll be using an initialization
file to handle this.
An initialization file collects data, loads files, and organizes information for an application. In this
example, it will load and define all necessary constants, create a database object, and set up an
automatic loading function for classes. Other functionality will be added later on as it becomes
necessary.
Create a file called init.inc.php, and place it in the core folder (/sys/core/init.inc.php). Inside,
add the following:

<?php


/*
* Include the necessary configuration info
*/
include_once ' /sys/config/db-cred.inc.php';

/*
* Define constants for configuration info
*/
foreach ( $C as $name => $val )
{
define($name, $val);
}

/*
* Create a PDO object
*/
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME;
$dbo = new PDO($dsn, DB_USER, DB_PASS);

/*
* Define the auto-load function for classes
*/
function __autoload($class)
{
$filename = " /sys/class/class." . $class . ".inc.php";
if ( file_exists($filename) )
{
CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

133

include_once $filename;
}
}

?>

An automatic loading function is called when a script attempts to instantiate a class that hasn’t been
loaded yet. It’s a convenient way to easily load classes into a script on demand. For more information on
automatic loading, visit
Creating an Index File to Pull It All Together
To see everything in action, modify index.php in the public folder. Inside, simply include the
initialization file and instantiate the Calendar class. Next, check if the class loaded properly, and output
the object’s structure if so:

<?php

/*
* Include necessary files
*/
include_once ' /sys/core/init.inc.php';

/*
* Load the calendar for January
*/
$cal = new Calendar($dbo, "2010-01-01 12:00:00");

if ( is_object ($cal) )
{
echo "<pre>", var_dump($cal), "</pre>";
}


?>

Once you navigate to http://localhost/, the following message is output:

object(Calendar)#2 (6) {
["_useDate:private"]=>
NULL
["_m:private"]=>
NULL
CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

134
["_y:private"]=>
NULL
["_daysInMonth:private"]=>
NULL
["_startDay:private"]=>
NULL
["db:protected"]=>
object(PDO)#3 (0) {
}
}
Setting Basic Properties
With all that infrastructure taken care of, you can get back to finishing the Calendar class’s constructor.
After checking the database object, the constructor needs to store several pieces of data about the
month with which it will be building a calendar.
First, it checks if a date was passed to the constructor; if so, that is stored in the $_useDate property;
otherwise, the current date is used.
Next, the date is converted to a UNIX timestamp (the number of seconds since the Unix epoch; read

more about this at before the month and year are extracted
and stored in $_m and $_y, respectively.
Finally, $_m and $_y are used to determine how many days are in the month being used and which
day of the week the month starts on.
The following bold code adds this functionality to the constructor:

<?php

class Calendar extends DB_Connect
{


private $_useDate;

private $_m;

private $_y;

private $_daysInMonth;
CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

135

private $_startDay;

public function __construct($dbo=NULL, $useDate=NULL)
{
/*
* Call the parent constructor to check for
* a database object

*/
parent::__construct($dbo);

/*
* Gather and store data relevant to the month
*/
if ( isset($useDate) )
{
$this->_useDate = $useDate;
}
else
{
$this->_useDate = date('Y-m-d H:i:s');
}

/*
* Convert to a timestamp, then determine the month
* and year to use when building the calendar
*/
$ts = strtotime($this->_useDate);
$this->_m = date('m', $ts);
$this->_y = date('Y', $ts);

/*
* Determine how many days are in the month
*/
$this->_daysInMonth = cal_days_in_month(
CAL_GREGORIAN,
$this->_m,
$this->_y

);

/*
* Determine what weekday the month starts on
*/
$ts = mktime(0, 0, 0, $this->_m, 1, $this->_y);
$this->_startDay = date('w', $ts);
}

CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

136
}

?>

Now all the properties that were previously NULL will have values when you reload
http://localhost/:

object(Calendar)#2 (6) {
["_useDate:private"]=>
string(19) "2010-01-01 12:00:00"
["_m:private"]=>
string(2) "01"
["_y:private"]=>
string(4) "2010"
["_daysInMonth:private"]=>
int(31)
["_startDay:private"]=>
string(1) "5"

["db:protected"]=>
object(PDO)#3 (0) {
}
}
Loading Events Data
To load data about events, you need to create a new method to access the database and retrieve them.
Because event data will be accessed in two ways (the second of which will be addressed later in this
chapter), the act of loading data will be kept generic for easy reuse.
This method will be private and named _loadEventData(). It accepts one optional parameter—the
ID of an event—and follows these steps to load events:
CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

137
1. Create a basic SELECT query to load the available fields from the events table.
2. Check if an ID was passed, and if so, add a WHERE clause to the query to return
only one event.
3. Otherwise, do both of the following:
• Find midnight of the first day of the month and 11:59:59PM on the last day
of the month.
• Add a WHERE BETWEEN clause to only load dates that fall within the current
month.
4. Execute the query.
5. Return an associative array of the results.
All put together, this method looks like so:

<?php

class Calendar extends DB_Connect
{



private $_useDate;

private $_m;

private $_y;

private $_daysInMonth;

private $_startDay;

public function __construct($dbo=NULL, $useDate=NULL) { }

/**
* Loads event(s) info into an array
*
* @param int $id an optional event ID to filter results
* @return array an array of events from the database
*/
private function _loadEventData($id=NULL)
{
$sql = "SELECT
`event_id`, `event_title`, `event_desc`,
`event_start`, `event_end`
FROM `events`";

/*
* If an event ID is supplied, add a WHERE clause
* so only that event is returned
*/

CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

138
if ( !empty($id) )
{
$sql .= "WHERE `event_id`=:id LIMIT 1";
}

/*
* Otherwise, load all events for the month in use
*/
else
{
/*
* Find the first and last days of the month
*/
$start_ts = mktime(0, 0, 0, $this->_m, 1, $this->_y);
$end_ts = mktime(23, 59, 59, $this->_m+1, 0, $this->_y);
$start_date = date('Y-m-d H:i:s', $start_ts);
$end_date = date('Y-m-d H:i:s', $end_ts);

/*
* Filter events to only those happening in the
* currently selected month
*/
$sql .= "WHERE `event_start`
BETWEEN '$start_date'
AND '$end_date'
ORDER BY `event_start`";
}


try
{
$stmt = $this->db->prepare($sql);

/*
* Bind the parameter if an ID was passed
*/
if ( !empty($id) )
{
$stmt->bindParam(":id", $id, PDO::PARAM_INT);
}

$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor();

return $results;
}
catch ( Exception $e )
{
die ( $e->getMessage() );
}
}
CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

139

}


?>
■ Note For the sake of brevity, nonreferenced methods are collapsed.
This method returns an array that, when using the test entries you entered into the database
previously, looks like this:

Array
(
[0] => Array
(
[event_id] => 1
[event_title] => New Year's Day
[event_desc] => Happy New Year!
[event_start] => 2010-01-01 00:00:00
[event_end] => 2010-01-01 23:59:59
)

[1] => Array
(
[event_id] => 2
[event_title] => Last Day of January
[event_desc] => Last day of the month! Yay!
[event_start] => 2010-01-31 00:00:00
[event_end] => 2010-01-31 23:59:59
)

)
Creating an Array of Event Objects for Use in the Calendar
The raw output of _loadEventData() isn’t immediately usable in the calendar. Because events need to be
displayed on the proper day, the events retrieved from _loadEventData() need to be grouped by the day
on which they occur. For easy reference, the event fields will be simplified as well.

The end goal is an array of events that will use the day of the month as its index, containing each
event as an object. The two test entries in your database should end up being stored like so when the
new method is complete:

Array
(
[1] => Array
(
[0] => Event Object
CHAPTER 4 ■ BUILD AN EVENTS CALENDAR

140
(
[id] => 1
[title] => New Year's Day
[description] => Happy New Year!
[start] => 2010-01-01 00:00:00
[end] => 2010-01-01 23:59:59
)

)

[31] => Array
(
[0] => Event Object
(
[id] => 2
[title] => Last Day of January
[description] => Last day of the month! Yay!
[start] => 2010-01-31 00:00:00

[end] => 2010-01-31 23:59:59
)

)

)
Creating an Event Class
To accomplish this, you must first create a new class called Event in the class folder
(/sys/class/class.event.inc.php). It will have five public properties: $id, $title, $description, $start,
and $end; and a constructor that will set each of those properties using the associative array returned by
the database query. Create the file, and insert the following code inside it:

<?php

/**
* Stores event information
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT License, available
* at
*
* @author Jason Lengstorf <>
* @copyright 2010 Ennui Design
* @license
*/
class Event
{

/**

×