1. Trang chủ
  2. » Công Nghệ Thông Tin

Beginning PHP6, Apache, MySQL Web Development- P21 ppsx

30 194 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 30
Dung lượng 382,08 KB

Nội dung

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 [...]... second of four transaction pages: . ‘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)); . ‘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)); . ‘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));

Ngày đăng: 03/07/2014, 07:20