About the Plug-in This plug-in accepts the name of a datafile containing Guestbook data and returns all the messages from that file.. Variables, Arrays, and Functions $data Array contain
Trang 1$fh = fopen($datafile, 'a');
if (!$fh) return -1;
if (flock($fh, LOCK_EX)) fwrite($fh, $data "\n");
flock($fh, LOCK_UN);
fclose($fh);
return 1;
}
Get Guestbook Once you have a Guestbook and the facility to post messages to it, you’ll also want to be able to display the messages This function goes most of the way towards that by fetching all the messages from the datafile and returning them in an array
It does this (rather than display them directly) to leave you in complete control over how you want the output to appear Figure 8-3 shows posts from a Guestbook simply being displayed as regular text with no special formatting
About the Plug-in
This plug-in accepts the name of a datafile containing Guestbook data and returns all the messages from that file Upon success it returns a two-element array, the first of which contains the number of posts The second element is a further array containing all the posts Or, upon failure, it returns a single-element array with the value FALSE It takes these arguments:
• $datafile A string containing the location of a Guestbook datafile.
• $order The order in which to return the messages If its value is “r”, then posts
are returned in reverse order, with newest posts first, otherwise posts are returned
in order from oldest to newest
Variables, Arrays, and Functions
$data Array containing sub-arrays, each with all the items extracted from a post
$posts Array containing the messages extracted from $datafile
$post The current post being processed
F IGURE 8-3 Using this plug-in it’s easy to list all your Guestbook posts.
53
Trang 2How It Works
This plug-in reads in a previously created and posted-to-Guestbook datafile and returns all the messages it contains If the file cannot be read, it returns a single-element array with the value FALSE
Once read in, the array $posts is populated with the contents of $datafile, which is split into separate entries using the explode() function with an argument of \n, making the newline character the split boundary The rtrim() function is also used to remove the final character, which is a \n newline and is not required
Next, the argument $order is tested If it contains the value “r”, then the order of messages returned needs to be reversed so the function array_reverse() is applied to $posts
With $posts now in the order required, a foreach loop then steps through the array, placing each element in turn into the variable $post From here the array $data (which was previously initialized as an empty array) then has another element added to it comprising
an array extracted from the data in $post This is done using the explode() function with
an argument of !1!, which is the token I chose to use to split fields in a record This separates out all the parts (name, e-mail, web site, and message) and returns an array, which
is assigned to the current element of the $data array
Finally a two-element array is returned, of which the first element contains the number
of messages returned, and the second contains an array of arrays, each sub-array containing the parts of a single message
How to Use It
To use this plug-in you only need to pass it the name of a datafile containing Guestbook data and an argument telling it which order to use when returning the messages, like this:
$result = PIPHP_GetGuestBook('guestbook.txt', 'f');
Then, you test $result[0] to see whether it contains the value FALSE If it does, the function call failed and there are no messages to display You can check for it like this:
if (!$result[0]) echo "Could not read file";
Otherwise, it contains a value representing the number of messages returned by the function You can display this number like this:
echo "There are $result[0] posts";
If posts exist, the second element will then contain an array of arrays, each main array element containing a sub-array of four elements representing, in order, the name, e-mail, web site, and message of a post You can therefore act on this data like this:
for ($j = 0 ; $j < $result[0] ; ++$j) {
for ($k = 0 ; $k < 4 ; ++$k) echo $result[1][$j][$k] "<br />";
echo "<br />";
}
Trang 3This code loops through all main elements in the array $result[1], with $result[1][0] being the first element of this array, and itself being an array with the following elements:
$result[1][0][0]
$result[1][0][1]
$result[1][0][2]
$result[1][0][3]
These four values represent the name, e-mail, web site, and message of the first post
The second post (if there is one) is returned in these four array elements (and so on):
$result[1][1][0]
$result[1][1][1]
$result[1][1][2]
$result[1][1][3]
Using these values it’s now up to you to create the styling and layout needed to make your Guestbook look just how you want it Displaying them is as easy as placing them after echo statements, like this:
echo $result[1][1][0];
echo $result[1][1][1];
echo $result[1][1][2];
echo $result[1][1][3];
The Plug-in
function PIPHP_GetGuestBook($datafile, $order) {
if (!file_exists($datafile)) return array(0);
$data = array();
$posts = explode("\n", rtrim(file_get_contents($datafile)));
if (strtolower($order) == 'r') $posts = array_reverse($posts);
foreach ($posts as $post) $data[] = explode('!1!', $post);
return array(count($posts), $data);
}
Post to Chat Some of the more popular features of a web site are messaging and chat facilities, particularly
if they are fast and easy to use, which this plug-in is—even though it’s only about 30 lines of actual code, without a sign of Java or Flash in sight
54
Trang 4I first wrote the predecessor of this chat in 1996 using Perl scripts and later transported
it to compiled C code and then, with the advent of PHP, due to its tremendous speed (even though it’s not compiled) I rewrote it again But the code’s format has remained pretty much the same: a simple text file that is continuously read from and written to, using file locking to prevent file corruption
It also uses a feature that predates Ajax (the sending of background requests to a server
to exchange data), but provides similar functionality in that messages appear in the browser when posted, without having to refresh the page Figure 8-4 shows this Post part of the chat engine being used to post a message, with and without flood control
About the Plug-in
This plug-in posts a message to a live chatroom and supports a number of parameters Upon success, the plug-in returns a value of 1 If the file could not be written to, then -1 is returned, or if flooding control is on and a duplicate post has been prevented, then 0 is returned If $message is empty or there are illegal | symbols in either $to or $from, then -2
is returned The plug-in takes these arguments:
• $datafile A string containing the location of a chatroom datafile
• $maxposts The maximum number of messages to retain at a time
• $maxlength The maximum message length in characters
• $from The username of the message poster
• $to The message recipient’s username—leave blank if the message is public
• $message The contents of the message
• $floodctrl If this has the value “on”, the same message cannot be reposted by
the same user within $maxposts messages
F IGURE 8-4 You can operate your own chatroom using this plug-in
Trang 5Variables, Arrays, and Functions
$data Array used to populate $datafile with blank messages
$fh File handle used to reference $datafile
$text String containing all but the first message in $datafile
$lines Array containing posts extracted from $text
$temp String containing the post number of the final post in the file
How It Works
The object of this plug-in is to remove the oldest message from the datafile and add the new message—if, that is, the new message is not a repeat, or flood control has not been enabled
The first thing it does if the datafile doesn’t exist is create it by putting together a collection of dummy blank posts in $data Each post is of the form: number|recipient|
sender|message The | symbols serving to separate the parts Therefore if, for example, the value in $maxposts is 20, then $data will be populated with 20 |||\n strings This ensures that, for an initial chat file, all fields in each post are blank and that each is terminated with a \n newline to separate records from each other This whole string is then saved to $datafile using the file_put_contents() function
At this point there is definitely a datafile of posts, either one just created or one that was preexisting So now the arguments passed to the plug-in are checked If $message is blank, or either of $from or $to contains a banned | symbol, then there was a problem In the former case, there is nothing to post, and in the latter the | symbols would corrupt the datafile and therefore are not allowed Ideally, when users enter your chatroom you will already have weeded out any such occurrences, but if not, this check will catch them A value of -2 is returned in either case
The | symbol can actually be useful in messages, so if any are encountered in $message they are converted to their HTML entity equivalent of | Also, if $message has more characters than the value specified in $maxlength, then $message is passed through the substr() function to truncate it to the maximum length allowed
With all the fields now prepared, the datafile is opened using the fopen() function and the file handle for manipulating it is assigned to $fh If $fh is FALSE, the file couldn’t be opened and so -1 is returned
Otherwise, the flock() function is called (see plug-in 52, Post to Guestbook for further
details) to ensure the program has exclusive access to the file so there will be no clashes of concurrent writes With the file lock obtained, the very first line of the file is returned using fgets() This is the oldest post and therefore it will be discarded—so the value returned is not used and is simply ignored
Next, the string variable $text is assigned the remaining contents of the file using the fread() function, with an argument of 100000 This tells the function to read in at most 100,000 characters from the file, up to the file’s end This should be more than you are likely
to need because, for example, 20 messages of 1,000 characters each would only occupy 20,000 bytes But you can easily change this value if you need to
Next, the argument $floodctrl is checked, and if it has the value “on”, then no repeated posts are allowed To check for this, the function strpos() is called, which