You should be taken back to the Character Database page, where you ’ ll see the new character listed, as shown in Figure 10 - 5... You can select any previously created characters in the
Trang 1< input type=”radio” name=”alignment” value=”evil”
< ?php echo ($character[‘alignment’]==’evil’) ? ‘checked=”checked”’ : ‘’; ? < > Evil
// 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 ‘ < > < 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
Trang 2if ($action == “Edit”) {
echo ‘ < input type=”submit” name=”action” value=”Delete Character” / >
echo ‘ < input type=”hidden” name=”character_id” value=”’
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
Trang 34 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
Trang 46 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
Trang 58 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
Trang 6$order = array(1 = > ‘alias ASC’,
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
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” >
Trang 7Next 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
Trang 8the 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
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
Trang 9$_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
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
Trang 10The 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 > < /
Trang 11power ASC’;
$result = mysql_query($query, $db) or die (mysql_error($db));
if (mysql_num_rows($result) > 0) { echo ‘ < select multiple name=”powers[]” >
while ($row = mysql_fetch_array($result)) {
if (isset($character_powers[$row[‘power_id’]])) { echo ‘ < option value=”’ $row[‘power_id’] ‘”
selected=”selected” >
} else { echo ‘ < option value=”’ $row[‘power_id’] ‘” >
} echo $row[‘power’] ‘ < /option >
} echo ‘ < /select >
} else { echo ‘ < > < strong > No Powers entered < /strong > < /p >
}mysql_free_result($result);
? < /td >
Note the [] in the select ’ s name attribute That is necessary for PHP to recognize the variable as an array when it gets posted to the char_transaction.php page This is a requirement for any field that might post with multiple values
Then the following code creates a set of radio buttons for “ good ” and “ evil ” Alignment The character ’ s alignment is preselected with the checked attribute
< td > Alignment: < /td >
< td > < input type=”radio” name=”alignment” value=”good”
< ?php echo ($character[‘alignment’]==’good’) ? ‘checked=”checked”’ : ‘’;
? < > Good < br/ >
input type=”radio” name=”alignment” value=”evil”
< ?php echo ($character[‘alignment’]==’evil’) ? ‘checked=”checked”’ : ‘’;
? < > Evil
< /td >
Remember what you did with the Powers field? Ditto all of that for the Enemies field
< td > Rivalries: < br/ > < small > < em > CTRL-click to select multiple enemies < /em > < /small >
< /td >
< td >
< ?php
$query = ‘SELECT character_id, alias FROM
comic_character WHERE
character_id != ‘ $character_id ‘ ORDER BY
Trang 12alias 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 the character entry form is in Edit mode, then the script will include a Delete Character button The
button won ’ t appear in Add mode, since you can ’ t delete a character you haven ’ t created yet Also,
the character ID is not passed through any other form fields, so you create a hidden field to hold that
information You need that ID if you are going to update an existing character, right? Of course, if you
are creating a new character, then the ID will be created for you when you insert all the appropriate data
if ($action == “Edit”) {
echo ‘ < input type=”submit” name=”action” value=”Delete Character” / >
echo ‘ < input type=”hidden” name=”character_id” value=”’
$character_id ‘” / >
}
Summar y
Whew! This chapter covered a lot of ground You learned about how to plan the design of your
application, including database design You learned how to normalize your data so that it can easily be
linked and manipulated without having redundant duplication You created a brand - new database for
your web site and started building your site by creating tables the application needed to access and
update
Congratulations! You ’ ve just created your first fully functioning web application with a relational
database back end (That ’ s going to look so good on your resume.)
This chapter is only the beginning, however With the knowledge you gained here, you can create almost
any application you desire Here are some examples of what you could do:
Content Management System (CMS): Create a data entry system that will allow users and
administrators to alter the content of the web site and your database without knowing any
HTML
❑
Trang 13Maintain a database of users visiting your site: You can enable user authentication, e - mail your
users to give them exciting news, sign them up for newsletters, and so on
Create an online e - commerce site: Create shopping carts where users can store the merchandise
they will purchase (This can be daunting — many choose to use a third - party shopping - cart application.)
Create an online discussion forum where your users can go to discuss how wonderful your
site looks!
These are just a few ideas In fact, you are going to see how to do each of these things over the course of upcoming chapters With a little imagination, you can come up with solutions to almost any problem you might face in building your site
If any of the ideas presented in this chapter are difficult for you to grasp, that ’ s okay — it is a large amount of new material crammed into only a few pages We expected you to learn a lot, especially if you are a beginning programmer The great thing about a book is that you can keep coming back! You will also be revisiting many of these concepts in later chapters For example, in Chapter 16, where you learn
to build your own forum, you will go through database normalization again, on a new set of databases You will also have many more opportunities to create SQL queries, some familiar and some new
For now, you have the basic knowledge for creating even the most complex sites You have the first incarnation installed on your server Take some time to play with your new toy
Now all you need to do is let all of your friends and family know about your cool new site If only you knew how to send e - mails using PHP Well, we ’ ll handle that in Chapter 11
Exercises
See how you might accomplish the following tasks:
1 Add a “ costume description ” field to the character record, and provide a way to modify the tume description
2 Modify the character listing to display the characters ’ locations alongside their powers
❑
❑
❑
Trang 15e - mail We are not talking about standard e - mail — we ’ re talking about sending out e - mails using PHP
Why would you want a server - side scripting language to send out e - mails? Perhaps you want to create a feedback form used for submitting information to an administrator ’ s e - mail address, as introduced in Chapter 9 Maybe you want certain errors to be automatically e - mailed to the webmaster Perhaps you would like to create an application that allows users to send their friends and family electronic postcards (Nod your head in vigorous agreement to the latter, here, because that is exactly what you are going to do!)
Specifically, this chapter covers:
Sending a basic e - mail Sending an HTML - formatted e - mail Using multipart messages
Sending images Receiving confirmation