</form> HERE; return $output; } // end smartRToEdit What makes this function smart is its ability to examine each field in the record and make a guess about what sort of field it is. Figure 12.13 shows the result of the smartRToEdit() program so you can compare it to the not-so-clever function in Figure 12.12. Determining the Field Type As far as this function is concerned, three field types in a record need to be han- dled differently. • Primary key. If a field is the primary key, its value needs to be passed on to the next program, but the user should not be able to edit it. • Foreign key. If a field is a foreign key reference to another table, the user should only be able to indirectly edit the value. The best approach is to have a drop-down list box that shows values the user will recognize. Each of these values corresponds to a key in that secondary record. For example, in Figure 12.13 there is a list box for the operationID field. The operationID field is a foreign key reference in the agent table. The ordinary rToEdit() 418 P H P 5 /M y S Q L P r o g r a m m i n g f o r t h e A b s o l u t e B e g i n n e r FIGURE 12.13 The smarter function prevents the user from editing the primary key and provides a drop-down list for all foreign key references. function allows the user to type any index number into the textbox with- out any real indication what data correlates to that index. This version builds a drop-down list showing operation names. The key value associated with those names is stored in the value attribute of each option. (Details to follow in the fieldToList() function.) The user doesn’t have to know anything about foreign key references or relational structures—he simply chooses an operation from a list. That list is dynamically generated each time the user chooses to add a record, so it always reflects all the opera- tions in the agency. • Neither a primary nor secondary key. In this case, I print a simple textbox so the user can input the value of the field. In all cases, the output will reflect the current value of the field. Working with the Primary Key The primary key value is much more important to the program than it is to the user. I decided to display it, but not to make it editable in any way. Primary keys should not be edited, but changed only by adding or deleting records. I relied upon some conventions to determine whether a field is a primary key. I assumed that the first field of the record (field number 0) is the primary key. This is a very common convention, but not universal. Since I created the data design in this case, I can be sure that the number 0 field in every table is the primary key. For that field, I simply printed the field name and value in an ordinary HTML table row. I added the key’s value in a hidden field so the next program has access to it. Recognizing Foreign Keys Unfortunately, there is no way (at least in MySQL or SQLite) to determine if a field is a foreign key reference. I had to rely on a naming convention to make sure my program recognizes a field as a foreign key reference. I decided that all foreign key fields in my database will have the foreign table’s name followed by the value ID. For example, a foreign key reference to the operation table will always be called operationID in my database. This is a smart convention to follow anyway, as it makes your field names easy to remember. It becomes critical in smartRToEdit() because it’s the only way to tell whether a field is a foreign key reference. I used an else if clause to check the name of any field that is not the primary key (which was checked in the if clause). The preg_match() function lets me use a powerful regular expression match to determine the field’s name. 419 C h a p t e r 1 2B u i l d i n g a T h r e e -T i e r e d D a t a A p p l i c a t i o n I used this statement to determine whether a field is a foreign key: } else if (preg_match(“/(.*)ID$/”, $col, $match)) { It uses a simple but powerful regular expression: /(.*)ID$/. This expression looks for any line that ends with ID. (Recall that the $ indicates the end of a string.) The .* indicates any number of characters. The parentheses around .* tell PHP to store all the characters before ID into a special array, called $match. Since there’s only one pattern to match in this expression, all the characters before ID contain the table name. So, this regular expression takes the name of a field and determines if it ends with ID. If so, the beginning part of the field name (everything but ID) is stored to $match[1]. If $col contains operationID, this line returns TRUE (because operationID ends with ID) and the table name (operation) is stored in $match[1]. Building the Foreign Key List Box If a field is a foreign key reference, it is necessary to build a list box containing some sort of meaningful value the user can read. Since I need this capability in a couple of places (and smartRToEdit() is already pretty complex), I build a new function called fieldToList(). This function (explained in detail later in the “Building a List Box from a Field” section of this chapter) builds a drop-down HTML list based on a table and field name. Rather than worrying about the details of the fieldToList() function here, I simply figured out what parameters it would need and printed that function’s results. Working with Regular Fields Any field that is not a primary or foreign key is handled by the else clause, which prints out an rToEdit()-style textbox for user input. This textbox handles all fields that allow ordinary user input, but will not trap for certain errors (such as string data being placed in numeric fields or data longer than the underlying field accepts). These would be good code improvement. If the data designer did not name foreign key references according to my convention, those fields are still editable with a textbox, but the errors that could happen with rToEdit() are worth concern. Committing a Record Update The end result of either rToEdit() or smartRToEdit() is an HTML form containing a table name and a bunch of field names and values. The updateRecord.php takes TRICK 420 P H P 5 /M y S Q L P r o g r a m m i n g f o r t h e A b s o l u t e B e g i n n e r these values and converts them into arrays before calling the updateRec() func- tion. It’s much easier to work with the fields and values as arrays than in the somewhat amorphous context they embody after smartRToEdit() or rToEdit(). function updateRec($tableName, $fields, $vals){ //expects name of a record, fields array values array //updates database with new values global $dbConn; $output = “”; $keyName = $fields[0]; $keyVal = $vals[0]; $query = “”; $query .= “UPDATE $tableName SET \n”; for ($i = 1; $i < count($fields); $i++){ $query .= $fields[$i]; $query .= “ = ‘“; $query .= $vals[$i]; $query .= “‘,\n”; } // end for loop //remove last comma from output $query = substr($query, 0, strlen($query) - 2); $query .= “\nWHERE $keyName = ‘$keyVal’”; $result = mysql_query($query, $dbConn); if ($result){ $query = “SELECT * FROM $tableName WHERE $keyName = ‘$keyVal’”; $output .= “<h3>update successful</h3>\n”; $output .= “new value of record:<br>”; $output .= qToTable($query); } else { $output .= “<h3>there was a problem </h3><pre>$query</pre>\n”; } // end if return $output; } // end updateRec 421 C h a p t e r 1 2B u i l d i n g a T h r e e -T i e r e d D a t a A p p l i c a t i o n The primary job of updateRec() is to build an SQL UPDATE statement based on the parameters passed to it. It is expecting a table name, an array containing field names, and another array containing field values. The UPDATE statement is pri- marily a list of field names and values, which can be easily obtained with a for loop stepping through the $fields and $vals arrays. Once the query has been created, it is submitted to the database. The success or failure of the update is reported back to the user. Deleting a Record Deleting a record is actually pretty easy compared to adding or updating. All that’s necessary is the table name, key field name, and key field value. The deleteRec() function accepts these parameters and uses them to build an SQL DELETE statement. As usual, the success or failure of the operation is returned as part of the output string. function delRec ($table, $keyName, $keyVal){ //deletes $keyVal record from $table global $dbConn; $output = “”; $query = “DELETE from $table WHERE $keyName = ‘$keyVal’”; print “query is $query<br>\n”; $result = mysql_query($query, $dbConn); if ($result){ $output = “<h3>Record successfully deleted</h3>\n”; } else { $output = “<h3>Error deleting record</h3>\n”; } //end if return $output; } // end delRec Adding a Record Adding a new record is much like editing a record. It is a two-step process. The first screen builds a page in which you can add a record. I used techniques from the smartRToEdit() function to ensure the primary and foreign key references are edited appropriately. function tToAdd($tableName){ //given table name, generates HTML form to add an entry to the //table. Works like smartRToEdit in recognizing foreign keys 422 P H P 5 /M y S Q L P r o g r a m m i n g f o r t h e A b s o l u t e B e g i n n e r . the end of a string.) The .* indicates any number of characters. The parentheses around .* tell PHP to store all the characters before ID into a special array, called $match. Since there’s only. is an HTML form containing a table name and a bunch of field names and values. The updateRecord .php takes TRICK 420 P H P 5 /M y S Q L P r o g r a m m i n g f o r t h e A b s o l u t e B e g i n n e r these