Adding Complex Data Structures to a Database
All data in a DBM-like database is extracted in string format, so you are limited to storing integers, strings, and doubles. Any other data type will be lost. Let's try to store an array, for example:
$array = array( 1, 2, 3, 4 ); $dbh = dba_open( "./data/test", "c", "gdbm" ) or die("Couldn't open test"); dba_insert("arraytest", $array, $dbh ); print gettype( dba_fetch("arraytest", $dbh) ); // prints "string"
We create an array and store it in the variable $array. We then open a database and attempt to insert an element called "arraytest", passing it the $array variable as the value. We then test the return type from dba_fetch() when attempting to access "arraytest" and ascertain that a string has been returned. In fact, if we printed the value stored in the "arraytest" record, we would get the string "Array". That would seem to wrap up any hopes for storing arrays and objects.
Fortunately, PHP provides a feature that allows you to "freeze-dry" values of any data type in string format. The data can then be stored in a database or file until it is needed. You can use this technique to store arrays and even objects in a database.
To convert the array in the previous example to a string, we must use the serialize() function. serialize() requires a value of any type and returns a string:
$array = array( 1, 2, 3, 4 ); print serialize( $array ); // prints a:4:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;}
We can now store this string in the database. When we want to resurrect it, we can use the unserialize() function. unserialize() requires a serialized string and returns a value of the appropriate data type.
This allows you to store complex data structures within the relatively simple format allowed by DBM-like databases. Listing 11.4 serializes an associative array for each of the items in our list of products and adds the result to a database.
Listing 11.4 Adding Complex Data to a Database
1: <html> 2: <head> 3: <title>Listing 11.4 Adding complex data to a database</title> 4: </head> 5: <body> 6: Adding complex data to database 7: <?php 8: $products = array( 9: "Sonic Screwdriver" => array( price=>"22.50", 10: shipping=>"12.50", 11: color=>"green" ), 12: "Tricorder" => array( price=>"55.50", 13: shipping=>"7.50", 14: color=>"red" ), 15: "ORAC AI" => array( price=>"2200.50", 16: shipping=>"34.50", 17: color=>"blue" ), 18: "HAL 2000" => array( price=>"4500.50", 19: shipping=>"18.50", 20: color=>"pink" ) 21: ); 22: $dbh = dba_open( "./data/products2", "c", "gdbm" ) 23: or die( "Couldn't open database" ); 24: while ( list ( $key, $value ) = each ( $products ) ) 25: dba_replace( $key, serialize( $value ), $dbh ); 26: dba_close( $dbh ); 27: ?> 28: </body> 29: </html>
We build a multidimensional array beginning on line 8, containing the product names as keys and four arrays of product information as values. We then open the database on line 22 and loop through the array on line 24. For each element, we pass the product name and a serialized version of the product array to dba_replace() (line 25). We then close the database (line 26).
Listing 11.5 writes the code that extracts this data.
Listing 11.5 Retrieving Serialized Data from a Database
1: <html> 2: <head> 3: <title>Listing 11.5 Retrieving serialized 4: data from a database</title> 5: </head> 6: <body> 7: Here at the Impossible Gadget Shop 8: we're offering the following exciting 9: products: 10: <p> 11: <table border=1 cellpadding ="5"> 12: <tr> 13: <td align="center"> <b>product</b></td> 14: <td align="center"> <b>color</b> </td> 15: <td align="center"> <b>shipping</b> </td> 16: <td align="center"> <b>price</b> </td> 17: </tr> 18: <?php 19: $dbh = dba_open( "./data/products2", "c", "gdbm" ) 20: or die( "Couldn't open database" ); 21: $key = dba_firstkey( $dbh ); 22: while ( $key != false ) { 23: $prodarray = unserialize( dba_fetch( $key, $dbh) ); 24: print "<tr><td align=\"left\"> $key </td>"; 25: print "<td align=\"left\">".$prodarray['color']." </td>\n"; 26: print "<td align=\"right\">\$".$prodarray['shipping']." </td>\n"; 27: print "<td align=\"right\">\$".$prodarray['price']." </td></tr>\n"; 28: $key = dba_nextkey( $dbh ); 29: } 30: dba_close( $dbh ); 31: ?> 32: </table> 33: </body> 34: </html>
Listing 11.5 is similar to the example in Listing 11.3. In this case though, we are displaying more fields. We open the database on line 19 and then use dba_firstkey() (line 21) and dba_nextkey() (line 28) to loop through each item in the database. We extract the value and use unserialize() to reconstruct the product array on line 23. It is then simple to print each element of the product array to the browser. Figure 11.2 shows the output from Listing 11.5.
Figure 11.2 Retrieving serialized data from a database.