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

Beginning PHP6, Apache, MySQL Web Development- P21 ppsx

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 (382.08 KB, 30 trang )

Chapter 16: Creating a Bulletin Board System
571
return $pagelinks;
}

function bbcode($db, $data) {
$sql = ‘SELECT
template, replacement
FROM
frm_bbcode’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
if (mysql_num_rows($result) > 0) {
while($row = mysql_fetch_array($result)) {
$bbcode[‘tpl’][] = ‘/’ .
html_entity_decode($row[‘template’], ENT_QUOTES). ‘/i’;
$bbcode[‘rep’][] = html_entity_decode($row[‘replacement’],
ENT_QUOTES);
}
$data1 = preg_replace($bbcode[‘tpl’], $bbcode[‘rep’], $data);
$count = 1;
while (($data1 != $data) and ($count < 4)) {
$count++;
$data = $data1;
$data1 = preg_replace($bbcode[‘tpl’], $bbcode[‘rep’], $data);
}
}
return $data;
}
? >
2. Create frm_config.inc.php . This sets up any constants or variables you may need in the
application. It loads admin settings and BBcode patterns into arrays to be used by the board.



< ?php
$sql = ‘SELECT * FROM frm_admin’;
$result = mysql_query($sql, $db) or die(mysql_error($db));

while ($row = mysql_fetch_array($result)) {
$admin[$row[‘constant’]][‘title’] = $row[‘title’];
$admin[$row[‘constant’]][‘value’] = $row[‘value’];
}
mysql_free_result($result);

$sql = ‘SELECT * FROM frm_bbcode’;
$result = mysql_query($sql, $db) or die(mysql_error($db));

while ($row = mysql_fetch_array($result)) {
$bbcode[$row[‘id’]][‘template’] = $row[‘template’];
$bbcode[$row[‘id’]][‘replacement’] = $row[‘replacement’];
}
mysql_free_result($result);

define(‘NEWPOST’, ‘ & raquo;’);
define(‘POSTLINK’, ‘ & diams;’);
? >
c16.indd 571c16.indd 571 12/10/08 6:06:04 PM12/10/08 6:06:04 PM
572
Part II: Comic Book Fan Site
3. Create frm_header.inc.php . This goes at the top of each page that gets displayed.
< ?php
session_start();
require ‘db.inc.php’;

require ‘frm_output_functions.inc.php’;

$db = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD) or
die (‘Unable to connect. Check your connection parameters.’);

mysql_select_db(MYSQL_DB, $db) or die(mysql_error($db));

require ‘frm_config.inc.php’;

$title = $admin[‘titlebar’][‘value’];
if (isset($pageTitle) and $pageTitle != ‘’) {
$title .= ‘ :: ‘ . $pageTitle;
}
if (isset($_SESSION[‘user_id’])) {
$userid = $_SESSION[‘user_id’];
} else {
$userid = null;
}
if (isset($_SESSION[‘access_lvl’])) {
$access_lvl = $_SESSION[‘access_lvl’];
} else {
$access_lvl = null;
}
if (isset($_SESSION[‘name’])) {
$username = $_SESSION[‘name’];
} else {
$username = null;
}
? >
< html >

< head >
< title > < ?php echo $title; ? > < /title >
< style type=”text/css” >
th { background-color: #999;}
td { vertical-align: top; }
.odd_row { background-color: #EEE; }
.even_row { background-color: #FFF; }
< /style >
< /head >
< body >
< h1 > < ?php echo $admin[‘title’][‘value’]; ? > < /h1 >
< h2 > < ?php echo $admin[‘description’][‘value’]; ? > < /h2 >
< ?php
if (isset($_SESSION[‘name’])) {
echo ‘ < p > Welcome, ‘ . $_SESSION[‘name’] . ‘ < /p > ’;
}
c16.indd 572c16.indd 572 12/10/08 6:06:04 PM12/10/08 6:06:04 PM
Chapter 16: Creating a Bulletin Board System
573
? >
< form method=”get” action=”frm_search.php” >
< div >
< input type=”text” name=”keywords”
< ?php
if (isset($_GET[‘keywords’])) {
echo ‘value=”’ . htmlspecialchars($_GET[‘keywords’]) . ‘” ‘;
}
? >
/ >
< input type=”submit” value=”Search”/ >

< /div >
< /form >
< ?php
echo ‘ < p > < a href=”frm_index.php” > Home < /a > ’;
if (!isset($_SESSION[‘user_id’])) {
echo ‘ | < a href=”frm_login.php” > Log In < /a > ’;
echo ‘ | < a href=”frm_useraccount.php” > Register < /a > ’;
} else {
echo ‘ | < a href=”frm_transact_user.php?action=Logout” > ’;
echo “Log out “ . $_SESSION[‘name’] . “ < /a > ”;
if ($_SESSION[‘access_lvl’] > 2) {
echo ‘ | < a href=”frm_admin.php” > Admin < /a > ’;
}
echo ‘ | < a href=”frm_useraccount.php” > Profile < /a > ’;
}
echo ‘ < /p >
’;
? >
4. Enter frm_footer.inc.php , which places a footer at the bottom of each page that gets
displayed:

< p > < ?php echo $admin[‘copyright’][‘value’]; ? > < /p >
< /body >
< /html >
How It Works
Most of the code in these scripts should be pretty understandable, by this point. You ’ ve seen functions
like
trim_body)_ before in similar functionality in Chapter 13 ’ s content management system (CMS)
application. Let ’ s look, however, at some of the more powerful functionality that
frm_output_

functions.inc.php
gives you.

Pagination
If you are not familiar with pagination, then we suggest you do a quick search — for anything — on
your favorite search engine. No matter what you search for, most likely you ’ ll have a large number of
links returned in response to your query. You should see some links somewhere that will take you to
more pages of search results, with the option of clicking next, previous, or a specific numbered page.
That, my friend, is pagination, and we are going to teach you how to do it for your own pages.
c16.indd 573c16.indd 573 12/10/08 6:06:05 PM12/10/08 6:06:05 PM
574
Part II: Comic Book Fan Site
When paginating your data, there are a few things you should have. The first, of course, is a large set of
data that you can ’ t display on one page. You also need to know how many rows of data you will display
per page, and how many total records you have in your result set. You also need to know how many
pages you will have access to at one time. For example, if you had 40 pages of data to display, you might
want to show links only for pages 1 through 10, or 12 through 21, and so forth. This is called the range .
Take a look at
show_topic() in frm_output_functions.inc.php . It ’ s quite lengthy, so we ’ ll
highlight for you the relevant code lines that affect pagination.

function show_topic($db, $topic_id, $user_id, $limit = 25) {

if (isset($_GET[‘page’])) {
$page = $_GET[‘page’];
} else {
$page = 1;
}

$start = ($page - 1) * $limit;


In a calling page, you pass in a number equaling the maximum number of records per page you want to
display. If you don ’ t pass a
page parameter in the URL to the web page, you assume you are on page 1.
Otherwise, you will be setting
page to the value passed to you in the URL. By knowing the page and the
limit (number of posts per page), you can calculate your
$start value (which will be used by the LIMIT
statement in the SQL statement used to retrieve rows). For example, if you are on page 3, and your limit
is 25 posts per page, then the third page will display rows 51 through 75.
Here is the SQL statement for returning posts. It may be long, but thankfully it is not overly complex. It
is simply four tables joined by the
JOIN statement. Please note the first line and the last line of the SQL
statement:

$sql = ‘SELECT SQL_CALC_FOUND_ROWS
p.id, p.subject, p.body, p.date_posted, p.date_updated,
u.name as author, u.id as author_id, u.signature as sig,
c.post_count as postcount, p.forum_id as forum_id,
f.forum_moderator as moderator, p.update_id, u2.name as updated_by
FROM
frm_forum f JOIN frm_posts p ON f.id = p.forum_id
JOIN frm_users u ON u.id = p.author_id
LEFT JOIN frm_users u2 ON u2.id = p.update_id
LEFT JOIN frm_post_count c ON u.id = c.user_id
WHERE
p.topic_id = ‘ . $topic_id . ‘ OR
p.id = ‘ . $topic_id . ‘
ORDER BY
p.topic_id, p.date_posted

LIMIT ‘ . $start . ‘, ‘ . $limit;
$result = mysql_query($sql, $db) or die(mysql_error($db));

$page_links = paginate($db, $limit);

This query will return a maximum of the number of rows in $limit . The problem is, you need to know
how many rows would have been returned if
LIMIT had not been used. You could execute the query again
c16.indd 574c16.indd 574 12/10/08 6:06:05 PM12/10/08 6:06:05 PM
Chapter 16: Creating a Bulletin Board System
575
without the LIMIT clause and retrieve the number of rows returned, but it turns out that isn ’ t necessary.
MySQL provides the
SQL_CALC_FOUND_ROWS command as a means for you to find out. In the first line,
immediately following
SELECT , you use the SQL command SQL_CALC_FOUND_ROWS . This doesn ’ t do
anything to the query directly, but does allow you to subsequently run the SQL command:

$sql = “SELECT FOUND_ROWS();”;

The MySQL function FOUND_ROWS() returns the number of rows that SQL_CALC_FOUND_ROWS found.

SQL_CALC_FOUND_ROWS makes the SELECT query take slightly longer to execute, but it is still more
efficient than running the query a second time to find out how many rows would have been returned if
you had not used a
LIMIT clause.
After you have your numbers, it ’ s time to create the page links. Take a look at the
paginate() function
in the same file:


function paginate($db, $limit = 10) {
global $admin;

$sql = ‘SELECT FOUND_ROWS();’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
$row = mysql_fetch_array($result);
$numrows = $row[0];
$pagelinks = ‘ < p > ’;
if ($numrows > $limit) {
if(isset($_GET[‘page’])){
$page = $_GET[‘page’];
} else {
$page = 1;
}

} else {
$pagelinks .= ‘ & lt; PREV & nbsp; & nbsp;NEXT & gt; & nbsp; & nbsp;’;
}
$pagelinks .= ‘ < /p > ’;
return $pagelinks;
}

The paginate function takes a $limit parameter, which, if it is not passed in to the function, you set to a
default value of 10. In order for the code to access the forum configuration variables, such as range and
limit,
$admin must be declared global because the scope of PHP ’ s execution is now in the function.
Otherwise, you would not be able to access the configuration.
As you can see, because you used
SELECT FOUND_ROWS() , $numrows contains the number of rows your
query returns. As long as the number of rows is larger than your limit, you ’ ll generate the pagination

links. Otherwise, you ’ ll just display inactive links.
Next, you grab the page variable, if it is set. If not, then you set
$page to 1. Then you determine
whether the < PREV link should be active or not. Obviously if you are on page 1, there is no previous
c16.indd 575c16.indd 575 12/10/08 6:06:05 PM12/10/08 6:06:05 PM
576
Part II: Comic Book Fan Site
page, and the link should not be active. Otherwise, the previous page is one less than the number of the
current page:

if($page == 1) {
$pagelinks .= ‘ & lt; PREV’;
} else {
$pageprev = $page - 1;
$pagelinks .= ‘ < a href=”’ . $currpage . ‘ & page=’ . $pageprev .
‘” > & lt; PREV < /a > ’;
}

The next chunk of code does a little bit of math. The number of pages is determined by dividing the total
number of rows returned by your previous
SELECT FOUND_ROWS() query by the number of posts per
page (
$numrows divided by $limit ) and rounding up.
The range is grabbed from
$admin[‘pagerange’][‘value’] and stored in $range . If it ’ s not
available, then
$range defaults to 7. This value determines how many pages are accessible via a link at
the bottom of the page. For example, if the range is 5, there are 13 pages, and you are currently viewing
page 6, you will have access to pages 4, 5, 6, 7, and 8:


< PREV [4] [5] 6 [7] [8] NEXT >

The “ ” shows you that there are more pages in that direction (either before or after).
$numofpages = ceil($numrows / $limit);
$range = $admin[‘pageRange’][‘value’];
if ($range == ‘’ or $range == 0) {
$range = 7;
}

The next few lines determine what range of pages to show you. In the previous example, if the $range is
5, but you are viewing page 2 out of 13 pages, the code should be smart enough to allow you access to
pages 1 through 5:

< PREV [1] 2 [3] [4] [5] NEXT >

As you can see, you are viewing page 2, you can get to pages 1 through 5 directly, and there are more
pages past 5. The piece of logic that determines which pages are available is the following:

$lrange = max(1, $page - (($range - 1) / 2));
$rrange = min($numofpages, $page + (($range - 1) / 2));
if (($rrange - $lrange) < ($range - 1)) {
if ($lrange == 1) {
$rrange = min($lrange + ($range - 1), $numofpages);
} else {
$lrange = max($rrange - ($range - 1), 0);
}
}

Then, the next part of the code renders the space between PREV and NEXT . If the lower range is higher
than 1, you put in to show that more pages can be accessed by clicking < PREV. Then, use the

$lrange
and
$rrange values to build the page number links. If the link corresponds to the current page, don ’ t
c16.indd 576c16.indd 576 12/10/08 6:06:06 PM12/10/08 6:06:06 PM
Chapter 16: Creating a Bulletin Board System
577
make it a link. Next, if the high end of the range of pages is lower than the total number of pages
available, you put in the to show that more pages can be accessed by clicking NEXT > .

if ($lrange > 1) {
$pagelinks .= ‘ ’;
} else {
$pagelinks .= ‘ & nbsp; & nbsp;’;
}
for($i = 1; $i < = $numofpages; $i++) {
if ($i == $page) {
$pagelinks .= $i;
} else {
if ($lrange < = $i and $i < = $rrange) {
$pagelinks .= ‘ < a href=”’ . $currpage . ‘ & page=’ . $i .
‘” > ’ . $i . ‘ < /a > ’;
}
}
}
if ($rrange < $numofpages) {
$pagelinks .= ‘ ’;
} else {
$pagelinks .= ‘ & nbsp; & nbsp;’;
}


The last part of the code renders NEXT > as an active or inactive link, depending on whether or not you
are looking at the last post of the thread, as it doesn ’ t make sense to go beyond the last page. Doing this
is relatively simple:

if(($numrows - ($limit * $page)) > 0) {
$pagenext = $page + 1;
$pagelinks .= ‘ < a href=”’ . $currpage . ‘ & page=’ . $pagenext .
‘” > NEXT & gt; < /a > ’;
} else {
$pagelinks .= ‘NEXT & gt;’;
}
} else {
$pagelinks .= ‘ & lt; PREV & nbsp; & nbsp;NEXT & gt; & nbsp; & nbsp;’;
}

Voil à ! You have a terrific, customizable, dynamically built pagination function. Your code generates
simple text links for the pages. However, you can easily take the logic presented here and modify the
code to implement CSS styles, images, or whatever else tickles your creative fancy.
Breadcrumbs
Once upon a time, there were two little children named Hansel and Gretel. They didn ’ t want to get lost
in the forest, so the story goes. So Hansel got the bright idea of dropping crumbs of bread along the path
so that they could find their way back. Birds ate the bread, the kids got lost, and then they stumbled
upon a house made out of gingerbread and candy (yum!). The little old lady who owned the house
wasn ’ t too keen on the idea of children eating holes through her walls, and so she enslaved them. Hansel
got fat eating German chocolates and candies while sitting in a cage, and Gretel was forced to do chores.
Then one day they stuffed the little old lady in an oven and ran home. The end.
c16.indd 577c16.indd 577 12/10/08 6:06:06 PM12/10/08 6:06:06 PM
578
Part II: Comic Book Fan Site
Exactly how Hansel and Gretel found their way home remains a mystery to us, since the birds ate the

breadcrumbs marking the trail, and that ’ s how they got lost in the first place! But aside from that, Hansel
had the right idea. By leaving some sort of trail behind them, they should have been able to navigate out
of any dark forest.
Some time ago, search engines came along, and some of them gave us the ability to find web sites based
on categories. Because there are so many sites out there that are very specialized, some of them might be
in a sub - sub - sub - subcategory. For example, say you wanted to view some sites in the Yahoo! directory
about PHP. You click the Computers and Internet category. Hmmm. Next, click Software, then Internet,
World Wide Web, Servers (ah, we ’ re getting close), Server Side Scripting, and (yes, finally!) PHP. Now
that you have reached this page, wouldn ’ t it be nice to remember how you got here? If you look near the
top of the screen, you should see something that looks like this:

Directory > Computers and Internet > Software > Internet >
World Wide Web > Servers > Server Side Scripting > PHP

It is a map of categories and subcategories telling you exactly how to get to the category you are looking
at. Someone (probably a fan of gingerbread houses, but don ’ t quote us on that) saw this “ map ” and
decided to call it a breadcrumb list. The name has stuck.
The truth is, breadcrumbs are very helpful, and they make a lot of sense for a bulletin board forum. They
can give you a map from the post you are reading to the thread it was in, to the forum the thread was in,
to the category the forum was in, and to the home page. By clicking on any part of the breadcrumb trail,
you can easily navigate to another part of the site. Perhaps one would look like this:

Home > Comic Book Movies > Spider-Man > This movie rocked! > I agree

You have implemented breadcrumbs for this application, and we will explain to you how it was done.
You could implement a breadcrumb system in many different ways (such as by folder structure). This is
just one way, and it is relatively simple.
The function itself takes two arguments,
$id and $getfrom . The argument $getfrom will either be F for
forum or P for post. There is no one standard separator for crumbs. Some people use

> , but we like to use
a bullet or dot. You can use whichever HTML entity you like:

function breadcrumb($db, $id, $get_from = ‘F’) {
$separator = ‘ & middot; ‘;

If you are in a post, then you want your breadcrumb to include a link to the forum, along with a
nonlinked indication of what thread you are in. You pass in the
topic_id to retrieve the right topic and
get the
forum_id from that topic and put it into the $id field. You also extract the name of the topic.
if ($get_from == ‘P’) {
$sql = ‘SELECT forum_id, subject FROM frm_posts WHERE id = ‘ . $id;
$result = mysql_query($sql, $db) or die(mysql_error($db));
$row = mysql_fetch_array($result);
$id = $row[‘forum_id’];
$topic = $row[‘subject’];
mysql_free_result($result);
}

c16.indd 578c16.indd 578 12/10/08 6:06:06 PM12/10/08 6:06:06 PM
Chapter 16: Creating a Bulletin Board System
579
Next, you call get_forum() with the $id that is now a forum_id . It returns a row that contains the
name and description of the forum. You don ’ t currently use the description, but you could use it as
alt
or
title attributes for the breadcrumb, if you wanted to.
$row = get_forum($db, $id);


At this point, you begin building the breadcrumb in the variable $bcrumb . Home is always first, and then
the separator. Next is either a link to the forum (if looking at a post), or simply the forum listed without a
link. Next comes the thread title for the post you are looking at.

$bcrumb = ‘ < a href=”frm_index.php” > Home < /a > ’ . $separator;
switch ($get_from) {
case ‘P’:
$bcrumb .= ‘ < a href=”frm_view_forum.php?f=’ . $id . ‘” > ’
. $row[‘name’] .
‘ < /a > ’ . $separator . $topic;
break;

case ‘F’:
$bcrumb .= $row[‘name’];
break;
}
return ‘ < h2 > ’ . $bcrumb . ‘ < /h2 > ’;
}

As we said before, this breadcrumb is not that difficult or complex, but we are sure that, armed with all
of the PHP knowledge you now have from reading this book, you could easily come up with a very
impressive breadcrumb function!
Next, take a look at your
frm_header.inc.php file. There isn ’ t much new to see here, but it gives us a
chance to discuss authentication with you for a moment.
A Last Look at User Authentication
The Comic Book Appreciation board uses user authentication, but it is by no means totally secure. For a
board application, it is probably secure enough. If this were human resources data containing sensitive
information, you might want to make it a bit more secure. This book does not attempt to help you create
a virtual Fort Knox. If you have such a need, we strongly suggest you look for a good book on security,

and perhaps look at a few online resources. A good start is
www.w3.org/Security/Faq/ .
Take a look at your security model, and see where there might be some places to improve it a bit. If you
look at most of the PHP pages that make up the application, you see that you check for a user ’ s access
level before displaying certain items. For example, examine
frm_header.inc.php .
Because
frm_header.inc.php is included at the top of almost every web page, you do most of your
user authentication there. By checking for the existence of the
user_id session variable, you know the
user is logged in. By checking if
access_lvl is greater than 2, you know whether the user has
administrator access. This allows you to customize the main menu according to the user ’ s login status
and his or her access level. It also allows you to address the user by name.

c16.indd 579c16.indd 579 12/10/08 6:06:07 PM12/10/08 6:06:07 PM
580
Part II: Comic Book Fan Site
if (isset($_SESSION[‘name’])) {
echo ‘ < p > Welcome, ‘ . $_SESSION[‘name’] . ‘ < /p > ’;
}

echo ‘ < p > < a href=”frm_index.php” > Home < /a > ’;
if (!isset($_SESSION[‘user_id’])) {
echo ‘ | < a href=”frm_login.php” > Log In < /a > ’;
echo ‘ | < a href=”frm_useraccount.php” > Register < /a > ’;
} else {
echo ‘ | < a href=”frm_transact_user.php?action=Logout” > ’;
echo “Log out “ . $_SESSION[‘name’] . “ < /a > ”;
if ($_SESSION[‘access_lvl’] > 2) {

echo ‘ | < a href=”frm_admin.php” > Admin < /a > ’;
}
echo ‘ | < a href=”frm_useraccount.php” > Profile < /a > ’;
}
echo ‘ < /p > ’;

If users are not logged in, you give them links to log in or register as a new user. If they are logged in,
they can log out or view their profile. If they are administrators, they will have access to the admin
functions.
Transaction Pages
The next group of files you ’ re going to create is the transaction pages. Like the reusable scripts just
covered, they don ’ t have anything pretty to show the end user, but they drive a large portion of the
behind - the - scenes board operations.
Try It Out Admin Transactions
The first file is responsible for all transactions related to the general administration of the board —
things like creating new forums, changing the board options, text substitutions, and so on.
1. Create frm_transact_admin.php , the first of four transaction pages. Admin forms post to
this page, which manipulates the data and then redirects the user to another page. Transaction
pages do not send any data to the client unless there is an error.

< ?php
require ‘db.inc.php’;
require ‘frm_output_functions.inc.php’;

$db = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD) or
die (‘Unable to connect. Check your connection parameters.’);

mysql_select_db(MYSQL_DB, $db) or die(mysql_error($db));

if (isset($_REQUEST[‘action’])) {

switch ($_REQUEST[‘action’]) {
c16.indd 580c16.indd 580 12/10/08 6:06:07 PM12/10/08 6:06:07 PM
Chapter 16: Creating a Bulletin Board System
581
case ‘Add Forum’:
if (isset($_POST[‘forumname’]) & & $_POST[‘forumname’] != ‘’ & &
isset($_POST[‘forumdesc’]) & & $_POST[‘forumdesc’] != ‘’) {
$sql = ‘INSERT IGNORE INTO frm_forum
(id, forum_name, forum_desc, forum_moderator)
VALUES
(NULL, “’ . htmlspecialchars($_POST[‘forumname’],
ENT_QUOTES) .
‘”, “’ . htmlspecialchars($_POST[‘forumdesc’],
ENT_QUOTES) .
‘”, ‘ . $_POST[‘forummod’][0] . ‘)’;
mysql_query($sql, $db) or die(mysql_error($db));
}
header(‘Location: frm_admin.php?option=forums’);
exit();
break;

case ‘Edit Forum’:
if (isset($_POST[‘forumname’]) & & $_POST[‘forumname’] != ‘’ & &
isset($_POST[‘forumdesc’]) & & $_POST[‘forumdesc’] != ‘’) {
$sql = ‘UPDATE frm_forum SET
forum_name = “’ . $_POST[‘forumname’] . ‘”,
forum_desc = “’ . $_POST[‘forumdesc’] . ‘”.
forum_moderator = ‘ . $_POST[‘forummod’][0] . ‘
WHERE
id = ‘ . $_POST[‘forum_id’];

mysql_query($sql, $db) or die(mysql_error($db));
}
header(‘Location: frm_admin.php?option=forums’);
exit();
break;

case ‘Modify User’:
header(‘Location: frm_useraccount.php?user=’ .
$_POST[‘userlist’][0]);
exit();
break;

case ‘Update’:
foreach ($_POST as $key = > $value) {
if ($key != ‘action’) {
$sql = ‘UPDATE frm_admin SET
value=”’ . $value . ‘”
WHERE
constant = “’ . $key . ‘”’;
mysql_query($sql, $db) or die(mysql_error($db));
}
}
header(‘Location: frm_admin.php’);
exit();
break;

c16.indd 581c16.indd 581 12/10/08 6:06:07 PM12/10/08 6:06:07 PM
582
Part II: Comic Book Fan Site
case ‘deleteForum’:

$sql = ‘DELETE FROM frm_forum WHERE id=’ . $_GET[‘f’];
mysql_query($sql, $db) or die(mysql_error($db));

$sql = ‘DELETE FROM forum_posts WHERE forum_id=’ . $_GET[‘f’];
mysql_query($sql, $db) or die(mysql_error($db));

header(‘Location: frm_admin.php?option=forums’);
exit();
break;

case ‘Add New’:
$sql = ‘INSERT INTO frm_bbcode
(id, template, replacement)
VALUES
(NULL, “’ . htmlentities($_POST[‘bbcode-tnew’],
ENT_QUOTES) . ‘”,
“’ . htmlentities($_POST[‘bbcode-rnew’],ENT_QUOTES) . ‘”)’;
mysql_query($sql, $db) or die(mysql_error($db));
header(‘Location: frm_admin.php?option=bbcode’);
exit();
break;

case ‘deleteBBCode’:
if (isset($_GET[‘b’])) {
$bbcodeid = $_GET[‘b’];
$sql = ‘DELETE FROM frm_bbcode WHERE id=’ . $bbcodeid;
mysql_query($sql, $db) or die(mysql_error($db));
}
header(‘Location: frm_admin.php?option=bbcode’);
exit();

break;

case ‘Update BBCodes’:
foreach($_POST as $key = > $value) {
if (substr($key, 0, 7) == ‘bbcode_’) {
$bbid = str_replace(‘bbcode_’, ‘’, $key);
if (substr($bbid, 0, 1) == ‘t’) {
$col = ‘template’;
} else {
$col = ‘replacement’;
}
$id = substr($bbid, 1);
$sql = ‘UPDATE frm_bbcode SET ‘ .
$col . ‘ = “’ . htmlentities($value, ENT_QUOTES) . ‘”
WHERE
id = ‘ . $id;
mysql_query($sql, $db) or die(mysql_error($db));
}
}
header(‘Location: frm_admin.php?option=bbcode’);
c16.indd 582c16.indd 582 12/10/08 6:06:07 PM12/10/08 6:06:07 PM
Chapter 16: Creating a Bulletin Board System
583
exit();
break;

default:
header(‘Location: frm_index.php’);
}
} else {

header(‘Location: frm_index.php’);
}
? >
How It Works
At this point, none of the code in frm_transact_admin.php should be unfamiliar to you. As seen
before in previous chapters, this script determines what action is to be performed in the database,
executes a corresponding query, then redirects the user to the appropriate page.
One of the more important things to remember from this page is the actions it handles, as shown here:

switch ($_REQUEST[‘action’]) {
case ‘Add Forum’:


case ‘Edit Forum’:


case ‘Modify User’:


case ‘Update’:


case ‘deleteForum’:


case ‘Add New’:


case ‘deleteBBCode’:



case ‘Update BBCodes’:


default:

}


You probably already understand how the switch statement works, so the key thing to keep in mind
is the different cases this specific switch processes. Remembering where a certain action takes place
can help you more quickly find and diagnose problems when they occur.

c16.indd 583c16.indd 583 12/10/08 6:06:08 PM12/10/08 6:06:08 PM
584
Part II: Comic Book Fan Site
Try It Out Post Transactions
The next transaction file controls all transactions related to forum posts — creating, editing, replying,
and so on.
1. Enter frm_transact_post.php , the second of four transaction pages:
< ?php
session_start();
require ‘db.inc.php’;
require ‘frm_output_functions.inc.php’;

$db = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD) or
die (‘Unable to connect. Check your connection parameters.’);

mysql_select_db(MYSQL_DB, $db) or die(mysql_error($db));


if (isset($_REQUEST[‘action’])) {
switch (strtoupper($_REQUEST[‘action’])) {
case ‘SUBMIT NEW POST’:
if (isset($_POST[‘subject’]) & & isset($_POST[‘body’]) & &
isset($_SESSION[‘user_id’])) {
$sql = ‘INSERT INTO frm_posts
(id, topic_id, forum_id, author_id, update_id,
date_posted,
date_updated, subject, body)
VALUES (
NULL, ‘ . $_POST[‘topic_id’] . ‘, ‘ .
$_POST[‘forum_id’] . ‘, ‘ . $_SESSION[‘user_id’] . ‘, 0,
“’ . date(‘Y-m-d H:i:s’) . ‘”, 0,
“’ . $_POST[‘subject’] . ‘”, “’ . $_POST[‘body’] . ‘”)’;
mysql_query($sql, $db) or die(mysql_error($db));
$postid = mysql_insert_id();

$sql = ‘INSERT IGNORE INTO frm_post_count
(user_id, post_count)
VALUES (‘ . $_SESSION[‘user_id’] . ‘,0)’;
mysql_query($sql, $db) or die(mysql_error($db));

$sql = ‘UPDATE frm_post_count SET
post_count = post_count + 1
WHERE
user_id = ‘ . $_SESSION[‘user_id’];
mysql_query($sql, $db) or die(mysql_error($db));
}
$topicid = ($_POST[‘topic_id’] == 0) ? $postid : $_POST[‘topic_id’];
header(‘Location: frm_view_topic.php?t=’ . $topicid . ‘#post’

. $postid);
exit();
break;

c16.indd 584c16.indd 584 12/10/08 6:06:08 PM12/10/08 6:06:08 PM
Chapter 16: Creating a Bulletin Board System
585
case ‘NEW TOPIC’:
header(‘Location: frm_compose.php?f=’ . $_POST[‘forum_id’]);
exit();
break;

case ‘EDIT’:
header(‘Location: frm_compose.php?a=edit & post=’ . $_POST[‘topic_id’]);
exit();
break;

case ‘SAVE CHANGES’:
if (isset($_POST[‘subject’]) & & isset($_POST[‘body’])) {
$sql = ‘UPDATE frm_posts SET
subject = “’ . $_POST[‘subject’] . ‘”,
update_id = ‘ . $_SESSION[‘user_id’] . ‘,
body = “’ . $_POST[‘body’] . ‘”,
date_updated = “’ . date(‘Y-m-d H:i:s’) . ‘”
WHERE
id = ‘ . $_POST[‘post’];
if (isset($_POST[‘author_id’])) {
$sql .= ‘ AND author_id = ‘ . $_POST[‘author_id’];
}
mysql_query($sql, $db) or die(mysql_error($db));

}
$redirID = ($_POST[‘topic_id’] == 0) ? $_POST[‘post’] :
$_POST[‘topic_id’];
header(‘Location: frm_view_topic.php?t=’ . $redirID);
exit();
break;

case ‘DELETE’:
if ($_REQUEST[‘post’]) {
$sql = ‘DELETE FROM frm_posts WHERE id = ‘ . $_REQUEST[‘post’];
mysql_query($sql, $db) or die(mysql_error($db));
}
header(‘Location: ‘ . $_REQUEST[‘r’]);
exit();
break;
}
} else {
header(‘Location: frm_index.php’);
}
? >
How It Works
Like the previous example, most of this is familiar by now. It ’ s good practice to keep in mind what
actions this transaction page performs. One bit of code worth noting is the addition of a new post.

c16.indd 585c16.indd 585 12/10/08 6:06:08 PM12/10/08 6:06:08 PM
586
Part II: Comic Book Fan Site
case ‘SUBMIT NEW POST’:
if (isset($_POST[‘subject’]) & & isset($_POST[‘body’]) & &
isset($_SESSION[‘user_id’])) {

$sql = ‘INSERT INTO frm_posts
(id, topic_id, forum_id, author_id, update_id, date_posted,
date_updated, subject, body)
VALUES (
NULL, ‘ . $_POST[‘topic_id’] . ‘, ‘ .
$_POST[‘forum_id’] . ‘, ‘ . $_SESSION[‘user_id’] . ‘, 0,
“’ . date(‘Y-m-d H:i:s’) . ‘”, 0,
“’ . $_POST[‘subject’] . ‘”, “’ . $_POST[‘body’] . ‘”)’;
mysql_query($sql, $db) or die(mysql_error($db));
$postid = mysql_insert_id();

$sql = ‘INSERT IGNORE INTO frm_post_count
(user_id, post_count)
VALUES (‘ . $_SESSION[‘user_id’] . ‘,0)’;
mysql_query($sql, $db) or die(mysql_error($db));

$sql = ‘UPDATE frm_post_count SET
post_count = post_count + 1
WHERE
user_id = ‘ . $_SESSION[‘user_id’];
mysql_query($sql, $db) or die(mysql_error($db));
}
$topicid = ($_POST[‘topic_id’] == 0) ? $postid : $_POST[‘topic_id’];
header(‘Location: frm_view_topic.php?t=’ . $topicid . ‘#post’ . $postid);
exit();
break;

Note how you first insert the post into the frm_posts table, then proceed to update the post count for
the user. In this case, you add the user into the
frm_post_count table, in case he or she doesn ’ t yet

exist there, and follow up by incrementing the user ’ s post count by one.

Try It Out User Transactions
Now you ’ re going to create the file responsible for all user - related transactions. Any time a user is
created or modified in the system, the database changes are performed here.
1. Create frm_transact_user.php , the third of four transaction pages. This one handles
functions related to the users, such as logging in.

< ?php
session_start();
require ‘db.inc.php’;

$db = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD) or
die (‘Unable to connect. Check your connection parameters.’);

mysql_select_db(MYSQL_DB, $db) or die(mysql_error($db));
c16.indd 586c16.indd 586 12/10/08 6:06:09 PM12/10/08 6:06:09 PM
Chapter 16: Creating a Bulletin Board System
587

if (isset($_REQUEST[‘action’])) {
switch ($_REQUEST[‘action’]) {
case ‘Login’:
if (isset($_POST[‘email’]) & & isset($_POST[‘passwd’])) {
$sql = ‘SELECT
id, access_lvl, name, last_login
FROM
frm_users
WHERE
email = “’ . $_POST[‘email’] . ‘” AND

password = “’ . $_POST[‘passwd’] . ‘”’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
if ($row = mysql_fetch_array($result)) {
$_SESSION[‘user_id’] = $row[‘id’];
$_SESSION[‘access_lvl’] = $row[‘access_lvl’];
$_SESSION[‘name’] = $row[‘name’];
$_SESSION[‘last_login’] = $row[‘last_login’];
$sql = ‘UPDATE frm_users SET
last_login = “’ . date(‘Y-m-d H:i:s’) . ‘”
WHERE
id = ‘ . $row[‘id’];
mysql_query($sql, $db) or die(mysql_error($db));
}
}
header(‘Location: frm_index.php’);
exit();
break;

case ‘Logout’:
session_unset();
session_destroy();
header(‘Location: frm_index.php’);
exit();
break;

case ‘Create Account’:
if (isset($_POST[‘name’]) & & isset($_POST[‘email’]) & &
isset($_POST[‘passwd’]) & & isset($_POST[‘passwd2’]) & &
$_POST[‘passwd’] == $_POST[‘passwd2’]) {
$sql = ‘INSERT INTO frm_users

(email, name, password, date_joined, last_login)
VALUES
(“’ . $_POST[‘email’] . ‘”, “’ . $_POST[‘name’] . ‘”,
“’ . $_POST[‘passwd’] . ‘”, “’ . date(‘Y-m-d H:i:s’) . ‘”,
“’ . date(‘Y-m-d H:i:s’) . ‘”)’;
mysql_query($sql, $db) or die(mysql_error($db));

$_SESSION[‘user_id’] = mysql_insert_id($db);
$_SESSION[‘access_lvl’] = 1;
$_SESSION[‘name’] = $_POST[‘name’];
$_SESSION[‘login_time’] = date(‘Y-m-d H:i:s’);
c16.indd 587c16.indd 587 12/10/08 6:06:09 PM12/10/08 6:06:09 PM
588
Part II: Comic Book Fan Site
}
header(‘Location: frm_index.php’);
exit();
break;

case ‘Modify Account’:
if (isset($_POST[‘name’]) & & isset($_POST[‘email’]) & &
isset($_POST[‘accesslvl’]) & & isset($_POST[‘userid’])) {
$sql = ‘UPDATE frm_users SET
email = “’ . $_POST[‘email’] . ‘”,
name = “’ . $_POST[‘name’] . ‘”,
access_lvl = ‘ . $_POST[‘accesslvl’] . ‘,
signature = “’ . $_POST[‘signature’] . ‘”
WHERE
id = ‘ . $_POST[‘userid’];
mysql_query($sql, $db) or die(mysql_error($db));

}
header(‘Location: frm_admin.php’);
exit();
break;

case ‘Edit Account’:
if (isset($_POST[‘name’]) & & isset($_POST[‘email’]) & &
isset($_POST[‘accesslvl’]) & & isset($_POST[‘userid’])) {
$chg_pw = FALSE;
if (!empty($_POST[‘oldpasswd’])) {
$sql = ‘SELECT
passwd
FROM
frm_users
WHERE
id = ‘ . $_POST[‘userid’];
$result = mysql_query($sql, $db) or die(mysql_error($db));
if ($row = mysql_fetch_array($result)) {
if ($row[‘passwd’] == $_POST[‘oldpasswd’] & &
isset($_POST[‘passwd’]) & & isset($_POST[‘passwd2’]) & &
$_POST[‘passwd’] == $_POST[‘passwd2’]) {
$chg_pw = TRUE;
} else {
header(‘Location: frm_useraccount
.php?error=nopassedit’);
exit();
break;
}
}
}

$sql = ‘UPDATE frm_users SET
email = “’ . $_POST[‘email’] . ‘”,
name=”’ . $_POST[‘name’] . ‘”,
access_lvl = ‘ . $_POST[‘accesslvl’] . ‘,
signature = “’ . $_POST[‘signature’] . ‘”’;
c16.indd 588c16.indd 588 12/10/08 6:06:09 PM12/10/08 6:06:09 PM
Chapter 16: Creating a Bulletin Board System
589
if ($chg_pw) {
$sql .= ‘”, passwd = “’ . $_POST[‘passwd’] . ‘”’;
}
$sql .= ‘ WHERE id=’ . $_POST[‘userid’];
mysql_query($sql, $db) or die(mysql_error($db));
}
header(‘Location: frm_useraccount.php?blah=’ . $_POST[‘userid’]);
break;

case ‘Send my reminder!’:
if (isset($_POST[‘email’])) {
$sql = ‘SELECT
passwd
FROM
frm_users
WHERE
email=”’ . $_POST[‘email’] . ‘”’;

$result = mysql_query($sql, $db) or die(mysql_error($db));

if (mysql_num_rows($result)) {
$row = mysql_fetch_array($result);


$headers = ‘From: ’ . “\r\n”;
$subject = ‘Comic site password reminder’;
$body = ‘Just a reminder, your password for the ‘ .
‘Comic Book Appreciation site is: ‘ . $row
[‘passwd’] .”\n\n”;
$body .= ‘You can use this to log in at http://’ .
$_SERVER[‘HTTP_HOST’] . dirname($_SERVER[‘PHP_SELF’]) .
‘/frm_login.php?e=’ . $_POST[‘email’];

mail($_POST[‘email’], $subject, $body, $headers);
}
}
header(‘Location: frm_login.php’);
break;
}
}
? >
How It Works
Like its predecessors, this transaction page follows the familiar “ determine action, query database,
return ” pattern. Most of the action processing is pretty straightforward, with the exception of the
account edit action. Let ’ s take a look at that specific case.

case ‘Edit Account’:
if (isset($_POST[‘name’]) & & isset($_POST[‘email’]) & &
isset($_POST[‘accesslvl’]) & & isset($_POST[‘userid’])) {

c16.indd 589c16.indd 589 12/10/08 6:06:10 PM12/10/08 6:06:10 PM
590
Part II: Comic Book Fan Site

This time instead of passing a simple query to the database, you must do some preliminary checks.
The script first checks to see if users have elected to change their password:

$chg_pw = FALSE;
if (!empty($_POST[‘oldpasswd’])) {

If this condition is met, then the script checks the old password in the database to see if a change has
truly been made. If not, the user is redirected back to the account edit page, and an error is flagged.

$sql = ‘SELECT
passwd
FROM
frm_users
WHERE
id = ‘ . $_POST[‘userid’];
$result = mysql_query($sql, $db) or die(mysql_error($db));
if ($row = mysql_fetch_array($result)) {
if ($row[‘passwd’] == $_POST[‘oldpasswd’] & &
isset($_POST[‘passwd’]) & & isset($_POST[‘passwd2’]) & &
$_POST[‘passwd’] == $_POST[‘passwd2’]) {
$chg_pw = TRUE;
} else {
header(‘Location: frm_useraccount.php?error=nopassedit’);
exit();
break;
}
}
}

Then, the account is finally updated.

$sql = ‘UPDATE frm_users SET
email = “’ . $_POST[‘email’] . ‘”,
name=”’ . $_POST[‘name’] . ‘”,
access_lvl = ‘ . $_POST[‘accesslvl’] . ‘,
signature = “’ . $_POST[‘signature’] . ‘”’;
if ($chg_pw) {
$sql .= ‘”, passwd = “’ . $_POST[‘passwd’] . ‘”’;
}
$sql .= ‘ WHERE id=’ . $_POST[‘userid’];
mysql_query($sql, $db) or die(mysql_error($db));
}
header(‘Location: frm_useraccount.php?blah=’ . $_POST[‘userid’]);
break;

The rest of the actions should be pretty self - explanatory. All actions update the database with
appropriate information, with the exception of the last case, where a reminder e - mail is sent to users if
they have forgotten their password.

c16.indd 590c16.indd 590 12/10/08 6:06:10 PM12/10/08 6:06:10 PM
Chapter 16: Creating a Bulletin Board System
591
Try It Out Removal Transactions
The last transaction page covers situations where forums or posts need to be deleted.
1. Create frm_transact_affirm.php . This is the only so - called transaction page that does send
data to the client. If a function requires confirmation, the user is sent here and redirected
forward.

< ?php
require ‘frm_header.inc.php’;
? >

< script type=”text/javascript” >
function deletePost(id, redir) {
if (id > 0) {
window.location = ‘frm_transact_post.php?action=delete & post=’ +
id + ‘ & r=’ + redir;
} else {
history.back();
}
}

function deleteForum(id) {
if (id > 0) {
window.location = ‘frm_transact_admin.php?action=deleteForum & f
=’ + id;
} else {
history.back();
}
}
< /script >
< ?php
switch (strtoupper($_REQUEST[‘action’])) {
case ‘DELETEPOST’:
$sql = ‘SELECT
id, topic_id, forum_id, subject
FROM
frm_posts
WHERE
id = ‘ . $_REQUEST[‘id’];
$result = mysql_query($sql, $db) or die(mysql_error($db));
$row = mysql_fetch_array($result);

if ($row[‘topic_id’] > 0) {
$msg = ‘Are you sure you wish to delete the post < br/ > ’ .
‘ < em > ’ . $row[‘subject’] . ‘ < /em > ?’;
$redir = htmlspecialchars(‘frm_view_topic.php?t=’ . $row[
‘topic_id’]);
} else {
$msg = ‘If you delete this post, all replies will be deleted as well. ‘ .
‘Are you sure you wish to delete the entire thread < br/ > ’ .
‘ < em > ’ . $row[‘subject’] . ‘ < /em > ?’;
c16.indd 591c16.indd 591 12/10/08 6:06:10 PM12/10/08 6:06:10 PM
592
Part II: Comic Book Fan Site
$redir = htmlspecialchars(‘frm_view_forum.php?f=’
. $row[‘forum_id’]);
}
echo ‘ < div > ’;
echo ‘ < h2 > DELETE POST? < /h2 > ’;
echo ‘ < p > ’ . $msg . ‘ < /p > ’;
echo ‘ < p > < a href=”#” onclick=”deletePost(‘ . $row[‘id’] . ‘, \’’ .
$redir . ‘\’); return false;” > Yes < /a > ‘ .
‘ < a href=”#” onclick=”history.back(); return false;” > No < /a > < /p > ’;
echo ‘ < /div > ’;
break;

case ‘DELETEFORUM’:
$sql = ‘SELECT
forum_name
FROM
frm_forum
WHERE

id=’ . $_REQUEST[‘f’];
$result = mysql_query($sql, $db) or die(mysql_error($db));
$row = mysql_fetch_array($result);
echo ‘ < div > ’;
echo ‘ < h2 > DELETE Forum? < /h2 > ’;
echo ‘ < p > If you delete this forum, all topics and replies will ‘ .
‘be deleted as well. Are you sure you wish to delete ‘ .
‘the entire forum < br/ > < em > ’ . $row[‘forum_name’] . ‘ < /em > ? < /p > ’;
echo ‘ < p > < a href=”#” onclick=”deleteForum(‘ . $_REQUEST[‘f’] .
‘); return false;” > Yes <
/a > < a href=”#” ‘ .
‘onclick=”history.back(); return false;” > No < /a > < /p > ’;
echo ‘ < /div > ’;
}
require_once ‘footer.php’;
? >
How It Works
An exception to the previous group of transaction pages, this script actually generates output to which
the user can respond. The
switch() statement determines which text to display:
switch (strtoupper($_REQUEST[‘action’])) {
case ‘DELETEPOST’:


case ‘DELETEFORUM’:

}

Each of the options outputs two buttons, one to confirm the action and one to go back. If users choose
to confirm, the button calls a bit of client - side JavaScript code to redirect them to the proper

transaction page:

function deletePost(id, redir) {
if (id > 0) {
window.location = ‘frm_transact_post.php?action=delete & post=’ +
id + ‘ & r=’ + redir;
} else {
c16.indd 592c16.indd 592 12/10/08 6:06:10 PM12/10/08 6:06:10 PM
Chapter 16: Creating a Bulletin Board System
593
history.back();
}
}

function deleteForum(id) {
if (id > 0) {
window.location = ‘frm_transact_admin.php?action=deleteForum & f=’ + id;
} else {
history.back();
}
}


Account Functionality
The next section of your bulletin board application deals with general account functionality. Here, you ’ ll
give users the ability to create their own account, request a forgotten password, and administer other
users. Let ’ s continue.
Try It Out Initial Login
The first thing you need to do is create the pages that allow users to create their account and log in to
the site.

1. Enter frm_login.php , the login page.
< ?php include ‘frm_header.inc.php’; ? >
< h1 > Member Login < /h1 >
< form method=”post” action=”frm_transact_user.php” >
< table >
< tr >
< td > < label for=”email” > Email Address: < /label > < /td >
< td > < input type=”text” id=”email” name=”email” maxlength=”100”/ > < /td >
< /tr > < tr >
< td > < label for=”passwd” > Password: < /label > < /td >
< td > < input type=”password” id=”passwd” name=”passwd” maxlength=”20”/ > < /td >
< /tr > < tr >
< td > < /td >
< td > < input type=”submit” class=”submit” name=”action” value=”Login”/ > < /td >
< /tr >
< /table >
< /form >
< p > Not a member yet? < a href=”frm_useraccount.php” > Create a new account! < /a > < /p >
< p > < a href=”frm_forgotpass.php” > Forgot your password? < /a > < /p >
< ?php include ‘frm_footer.inc.php’; ? >
c16.indd 593c16.indd 593 12/10/08 6:06:11 PM12/10/08 6:06:11 PM
594
Part II: Comic Book Fan Site
2. Create frm_index.php , the home page. This is the page users will first see when they view
the board.

< ?php
require ‘frm_header.inc.php’;

$sql = ‘SELECT

f.id as id, f.forum_name as forum, f.forum_desc as description,
COUNT(forum_id) as threads, u.name as moderator
FROM
frm_forum f LEFT JOIN frm_posts p ON f.id = p.forum_id AND
p.topic_id = 0
LEFT JOIN frm_users u ON f.forum_moderator = u.id
GROUP BY
f.id’;
$result = mysql_query($sql, $db) or die(mysql_error($db) . $sql);

if (mysql_num_rows($result) == 0) {
echo ‘ < h2 > There are currently no forums to view. < /h2 > ’;
} else {
? >
< table >
< tr >
< th > Forum < /th >
< th > Threads < /th >
< th > Moderator < /th >
< /tr >
< ?php
$odd = true;
while ($row = mysql_fetch_array($result)) {
echo ($odd == true) ? ‘ < tr class=”odd_row” > ’ : ‘ < tr class=
”even_row” > ’;
$odd = !$odd;
echo ‘ < td > < a href=”frm_view_forum.php?f=’ . $row[‘id’] . ‘” > ’ .
$row[‘forum’] . ‘ < /a > < br/ > ’ . $row[‘description’] . ‘ < /td > ’;
echo ‘ < td style=”text-align: center;” > ’ . $row[‘threads’] . ‘ < /td > ’;
echo ‘ < td

> ’ . $row[‘moderator’] . ‘ < /td > ’;
echo ‘ < /tr > ’;
}
echo ‘ < /table > ’;
}


require ‘frm_footer.inc.php’;
? >

c16.indd 594c16.indd 594 12/10/08 6:06:11 PM12/10/08 6:06:11 PM
Chapter 16: Creating a Bulletin Board System
595
3. Create frm_forgotpass.php . This page is displayed if the user forgets his or her password.
< ?php include ‘frm_header.inc.php’; ? >
< h2 > Email Password Reminder < /h2 >
< p > Forgot your password? Just enter your email address, and we’ll email
you a new one! < /p >
< form method=”post” action=”frm_transact_user.php” >
< div >
< label for=”email” > Email Address: < /label >
< input type=”text” id=”email” name=”email” maxlength=”100”/ >
< input type=”submit” name=”action” value=”Send my reminder!”/ >
< /div >
< /form >
< ?php include ‘frm_footer.inc.php’; ? >
4. Load frm_login.php in your browser. You are taken to the login page. Observe the link at
the bottom of the login screen, “ Forgot your password? ” A user who cannot remember his or
her password can click this link and enter the e - mail address submitted when the account was
created. If he or she is verified to be a valid user, the password will be sent to the e - mail

address given. You can try this out yourself if you like, assuming you are using a legitimate
e - mail address (and not the default).
5. Enter your password, and click the Login button. You should now see the home page of the
CBA board application (see Figure 16 - 2 ).
Figure 16-2
c16.indd 595c16.indd 595 12/10/08 6:06:11 PM12/10/08 6:06:11 PM

×