Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 30 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
30
Dung lượng
676,32 KB
Nội dung
Chapter 10: Building Databases 301 < input type=”radio” name=”alignment” value=”evil” < ?php echo ($character[‘alignment’]==’evil’) ? ‘checked=”checked”’ : ‘’; ? < / > Evil < /td > < /tr > < tr > < /tr > < tr > < td > Rivalries: < br/ > < small > < em > CTRL-click to select multiple enemies < /em > < /small > < /td > < td > < ?php // retrieve and present the list of existing characters (excluding the character // being edited) $query = ‘SELECT character_id, alias FROM comic_character WHERE character_id != ‘ . $character_id . ‘ ORDER BY alias ASC’; $result = mysql_query($query, $db) or die (mysql_error($db)); if (mysql_num_rows($result) > 0) { echo ‘ < select multiple name=”rivalries[]” > ’; while ($row = mysql_fetch_array($result)) { if (isset($rivalries[$row[‘character_id’]])) { echo ‘ < option value=”’ . $row[‘character_id’] . ‘” selected=”selected” > ’; } else { echo ‘ < option value=”’ . $row[‘character_id’] . ‘” > ’; } echo $row[‘alias’] . ‘ < /option > ’; } echo ‘ < /select > ’; } else { echo ‘ < p > < strong > No Characters entered < /strong > < /p > ’; } mysql_free_result($result); ? > < /td > < /tr > < tr > < td colspan=”2” > < input type=”submit” name=”action” value=” < ?php echo $action; ? > Character” / > < input type=”reset” value=”Reset” > < ?php c10.indd 301c10.indd 301 12/10/08 6:00:03 PM12/10/08 6:00:03 PM Part II: Comic Book Fan Site 302 if ($action == “Edit”) { echo ‘ < input type=”submit” name=”action” value=”Delete Character” / > ’; echo ‘ < input type=”hidden” name=”character_id” value=”’ . $character_id . ‘” / > ’; } ? > < /td > < /tr > < /table > < /form > < p > < a href=”list_characters.php” > Return to Home Page < /a > < /p > < /body > < /html > 3. Open your browser and point it to the location of list_characters.php . This is your Character Database home page. It should look something like Figure 10 - 3 . But because you don ’ t currently have any characters to look at, let ’ s move on. Figure 10-3 c10.indd 302c10.indd 302 12/10/08 6:00:04 PM12/10/08 6:00:04 PM Chapter 10: Building Databases 303 4. Click the Add New Character link. A new page appears, ready for your data input, which should look like that in Figure 10 - 4 . You will notice that the powers you entered are choices in the Powers field. Figure 10-4 5. Enter the appropriate data for your character, and click Add Character. You should be taken back to the Character Database page, where you ’ ll see the new character listed, as shown in Figure 10 - 5 . c10.indd 303c10.indd 303 12/10/08 6:00:04 PM12/10/08 6:00:04 PM Part II: Comic Book Fan Site 304 6. If you click New Character again, you now see an extra field for rivalries. You can select any previously created characters in the database as the current character ’ s enemies. 7. From the home page, click one of your characters ’ names. The Edit Character page loads again, and the character ’ s data will be automatically entered into the fields (see Figure 10 - 6 ). If you look at the URL for this page, you see ?id=# at the end, where # is the character ’ s number. Figure 10-5 c10.indd 304c10.indd 304 12/10/08 6:00:04 PM12/10/08 6:00:04 PM Chapter 10: Building Databases 305 8. Change some of the data, and click Edit Character. You are taken back to the Character Database page, where you should immediately see the results of your changes. In fact, if you selected an enemy for this character, you should see the results change in the enemy ’ s row as well. How It Works You created two different files in this exercise, so we ’ re going to take them apart and look at them each individually here. list_characters.php The list_characters.php page has an optional parameter that can be passed: ?o=# , where # is 1, 2, or 3. This code retrieves that variable if it exists and converts it to the appropriate value if necessary to determine on which column the display should be sorted. If some smart - aleck types in an invalid value, or if no value is passed at all, then the script will default its value to 1. Figure 10-6 c10.indd 305c10.indd 305 12/10/08 6:00:05 PM12/10/08 6:00:05 PM Part II: Comic Book Fan Site 306 $order = array(1 = > ‘alias ASC’, 2 = > ‘real_name ASC’, 3 = > ‘alignment ASC, alias ASC’); $o = (isset($_GET[‘o’]) & & ctype_digit($_GET[‘o’])) ? $_GET[‘o’] : 1; if (!in_array($o, array_keys($order))) { $o = 1; } This value determines which column the character display will be sorted on: 1 is by alias, 2 is by real name, and 3 is first by alignment and then by alias. You will use the value $o as the key to your order array which will be appended to the appropriate SQL statement later. You are going to build a table of characters in a moment. A SELECT query retrieves the list of characters sorted appropriately, and then the number of records is checked. If there are character records returned, then the table is constructed, but otherwise you want to display a “ No Characters ” message. $query = ‘SELECT character_id, alias, real_name, alignment FROM comic_character ORDER BY ‘ . $order[$o]; $result = mysql_query($query, $db) or die (mysql_error($db)); if (mysql_num_rows($result) > 0) { // } else { echo ‘ < p > < strong > No Characters entered < /strong > < /p > ’; } The column headers for the Alias, Real Name, and Alignment columns are actually links back to the same page, but with different sort parameters appended to the address, so the viewer can sort the table to his or her heart ’ s content by clicking on them. echo ‘ < tr > < th > < a href=”’ . $_SERVER[‘PHP_SELF’] . ‘?o=1” > Alias < /a > < /th > ’; echo ‘ < th > < a href=”’ . $_SERVER[‘PHP_SELF’] . ‘?o=2” > Real Name < /a > < /th > ’; echo ‘ < th > < a href=”’ . $_SERVER[‘PHP_SELF’] . ‘?o=3” > Alignment < /a > < /th > ’; echo ‘ < th > Powers < /th > ’; echo ‘ < th > Enemies < /th > < /tr > ’; Each row is provided with an alternating odd/even class attribute, as you have done in several earlier chapters, so they can be colorized. Alternating the background color of the rows makes it easier for your users to read them. You also make the character ’ s name a link to the edit_character.php page so that by clicking on it the user can edit the character ’ s details. $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=”edit_character.php?id=’ . $row[‘character_id’] . ‘” > ’ . $row[‘alias’] . ‘ < /a > < /td > ’; echo ‘ < td > ’ . $row[‘real_name’] . ‘ < /td > ’; echo ‘ < td > ’ . $row[‘alignment’] . ‘ < /td > ’; c10.indd 306c10.indd 306 12/10/08 6:00:05 PM12/10/08 6:00:05 PM Chapter 10: Building Databases 307 Next are two other SELECT statements to retrieve the appropriate data for the remaining columns: powers and rivalries. Because they are executed within a loop that is processing your first query ’ s results, $query2 , $result2 and $row2 variables are used, so you don ’ t overwrite the first query ’ s results that are still needed. The first SELECT statement fetches the character ’ s powers by JOIN ing the comic_power and comic_ character_power tables. If powers are returned, then they are listed in the table, but if no powers have been assigned to the character, then “ none ” is displayed. $query2 = ‘SELECT power FROM comic_power p JOIN comic_character_power cp ON p.power_id = cp.power_id WHERE cp.character_id = ‘ . $row[‘character_id’] . ‘ ORDER BY power ASC’; $result2 = mysql_query($query2, $db) or die (mysql_error($db)); if (mysql_num_rows($result2) > 0) { $powers = array(); while ($row2 = mysql_fetch_assoc($result2)) { $powers[] = $row2[‘power’]; } echo ‘ < td > ’ . implode(‘, ‘, $powers) . ‘ < /td > ’; } else { echo ‘ < td > none < /td > ’; } mysql_free_result($result2); The second SELECT statement fetches the character ’ s rivals. This one is similar to the previous M:N query, with a couple of exceptions. First of all, you are linking the character table twice. You can see that you are creating two instances of that table, one for the hero character and one for the villain character. This distinction is very important. The other exception is the ON statement. You have characters that you are attempting to link to other characters and enemies. Call them opponents, nemeses, or whatever. Typically, you expect good versus evil, and vice versa. However, you are allowing any character to be the enemy of any other character. That makes linking more interesting, because you are using a table a with a hero_id and villain_id . If you have two evil characters who are enemies to each other, which one gets stored in hero_id ? The answer is that it doesn ’ t matter. What you want to do is to make sure that you not only don ’ t have any duplicates in the comic_rivalry table, but also that you don ’ t have what we call reverse duplication. In other words, if you have a row with hero_id=3 and villain_id=7 , then hero_id=7 and villain_ id=3 must be considered a duplicate. There is no way to prevent that in MySQL using primary keys, so you must take care of that contingency in your code. You do that in a couple of places. In this instance, you are combining two queries into one. The first one grabs all instances of each character where there character ’ s ID is in the hero_id field, and his enemies ’ IDs are in the villain_id field. The second part of the ON statement reverses that and pulls all instances of each character where c10.indd 307c10.indd 307 12/10/08 6:00:05 PM12/10/08 6:00:05 PM Part II: Comic Book Fan Site 308 the character ’ s ID is in the villain field, and his enemies ’ IDs are in the hero_id field. This does not prevent reverse duplication (that is handled elsewhere), but it does make sure you have grabbed every possible link to a character ’ s enemy. Again, if enemies are returned, then they are listed in the table. Otherwise, “ none ” is displayed. $query2 = ‘SELECT c2.alias FROM comic_character c1 JOIN comic_character c2 JOIN comic_rivalry r ON (c1.character_id = r.hero_id AND c2.character_id = r.villain_id) OR (c2.character_id = r.hero_id AND c1.character_id = r.villain_id) WHERE c1.character_id = ‘ . $row[‘character_id’] . ‘ ORDER BY c2.alias ASC’; $result2 = mysql_query($query2, $db) or die (mysql_error($db)); if (mysql_num_rows($result2) > 0) { $aliases = array(); while ($row2 = mysql_fetch_assoc($result2)) { $aliases[] = $row2[‘alias’]; } echo ‘ < td > ’ . implode(‘, ‘, $aliases) . ‘ < /td > ’; } else { echo ‘ < td > none < /td > ’; } mysql_free_result($result2); edit_character.php This file does double duty so it ’ s a little longer. But a lot of it is HTML, and much of what it does you have already done before, so this shouldn ’ t be too difficult. The default functionality of this page is Add Character mode. If there is a value in $_GET[‘id’] other than 0, the script will pull the data and change the default values. $action = ‘Add’; $character = array(‘alias’ = > ‘’, ‘real_name’ = > ‘’, ‘alignment’ = > ‘good’, ‘address’ = > ‘’, ‘city’ = > ‘’, ‘state’ = > ‘’, ‘zipcode_id’ = > ‘’); $character_powers = array(); $rivalries = array(); $character_id = (isset($_GET[‘id’]) & & ctype_digit($_GET[‘id’])) ? c10.indd 308c10.indd 308 12/10/08 6:00:06 PM12/10/08 6:00:06 PM Chapter 10: Building Databases 309 $_GET[‘id’] : 0; if ($character_id != 0) { // } Next, the script gets the basic information about the character from the comic_character , comic_lair , and comic_zipcode tables. $query = ‘SELECT c.alias, c.real_name, c.alignment, l.address, z.city, z.state, z.zipcode_id FROM comic_character c, comic_lair l, comic_zipcode z WHERE z.zipcode_id = l.zipcode_id AND c.lair_id = l.lair_id AND c.character_id = ‘ . $character_id; $result = mysql_query($query, $db) or die (mysql_error($db)); if (mysql_num_rows($result) > 0) { $action = ‘Edit’; $character = mysql_fetch_assoc($result); } mysql_free_result($result); You may realize that the query is also a JOIN if you are an astute reader, although the JOIN keyword is not used. You can identify such a JOIN because there are two or more tables, and the WHERE clause matches columns from each of the tables. The JOIN in this case is implied, and ON has integrated into the WHERE clause. It isn ’ t until we are sure that a character with the provided ID really exists in the database that we switch the page ’ s action to Edit mode, which acts as a failsafe if someone were to supply an invalid character ID. If the value of $action has been changed, then the script will continue retrieving the list of superpowers and rivals for the character. if ($action == ‘Edit’) { $query = ‘SELECT power_id FROM comic_character_power WHERE character_id = ‘ . $character_id; $result = mysql_query($query, $db) or die (mysql_error($db)); if (mysql_num_rows($result) > 0) { while ($row = mysql_fetch_array($result)) { $character_powers[$row[‘power_id’]] = true; } } mysql_free_result($result); $query = ‘SELECT c2.character_id c10.indd 309c10.indd 309 12/10/08 6:00:06 PM12/10/08 6:00:06 PM Part II: Comic Book Fan Site 310 FROM comic_character c1 JOIN comic_character c2 JOIN comic_rivalry r ON (c1.character_id = r.hero_id AND c2.character_id = r.villain_id) OR (c2.character_id = r.hero_id AND c1.character_id = r.villain_id) WHERE c1.character_id = ‘ . $character_id . ‘ ORDER BY c2.alias ASC’; $result = mysql_query($query, $db) or die (mysql_error($db)); $rivalries = array(); if (mysql_num_rows($result) > 0) { while ($row = mysql_fetch_array($result)) { $rivalries[$row[‘character_id’]] = true; } } } The queries only retrieve the power IDs and rival IDs and store them in the appropriate array for later use. They will be used in the form ’ s Powers and Rivalries fields so each assigned to the character will be automatically selected. Note the similarity of the SQL statement that retrieves the list of rivalries to the one earlier in list_ characters.php . You next build the HTML form and insert the values into the appropriate places as defaults. This is how you fill in the fields with character data. < td > Character Name: < /td > < td > < input type=”text” name=”alias” size=”40” maxlength=”40” value=” < ?php echo $character[‘alias’];? > ” > < /td > When you build the Powers select field, the script loops through each power in the database and checks its ID against the list gathered earlier and stored in the $powers array. If that power ’ s key exists in the $powers array, then the script sets the option element ’ s selected attribute so that it will appear preselected in the form. In this way, the script builds a field of all powers where the character ’ s chosen powers are selected in the list. Neat, huh? < td > Powers: < br/ > < small > < em > CTRL-click to select multiple powers < /em > < / small > < /td > < td > < ?php $query = ‘SELECT power_id, power FROM comic_power ORDER BY c10.indd 310c10.indd 310 12/10/08 6:00:06 PM12/10/08 6:00:06 PM [...]... as listed in db.inc.php You wrote this file in Chapter 10, and it defines the constants you use to connect to the MySQL database $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)); Next, you created the pc_image table in the database, containing three columns: image_id to store... db_ch11-1.php Modify the code appropriately if you are using a different number of postcards, etc . $character_id; $result = mysql_ query($query, $db) or die (mysql_ error($db)); if (mysql_ num_rows($result) > 0) { $action = ‘Edit’; $character = mysql_ fetch_assoc($result); } mysql_ free_result($result); . mysql_ query($query, $db) or die (mysql_ error($db)); if (mysql_ num_rows($result) > 0) { while ($row = mysql_ fetch_array($result)) { $character_powers[$row[‘power_id’]] = true; } } mysql_ free_result($result); . BY c2.alias ASC’; $result2 = mysql_ query($query2, $db) or die (mysql_ error($db)); if (mysql_ num_rows($result2) > 0) { $aliases = array(); while ($row2 = mysql_ fetch_assoc($result2)) {