[ Team LiB ] Previous Section Next Section

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 enables 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 enables you to store complex data structures within the relatively simple format allowed by DBM-like databases. Listing 12.4 serializes an associative array for each of the items in our list of products and adds the result to a database.

Listing 12.4 Adding Complex Data to a Database
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 12.4 Adding Complex Data to a Database</title>
 7: </head>
 8: <body>
 9: <div>
10: Adding complex data to database
11: <?php
12: $products = array(
13:     "Sonic Screwdriver" => array( "price"=>22.50,
14:                    "shipping"=>12.50,
15:                    "color"=>"green" ),
16:     "Tricorder"    => array( "price"=>55.50,
17:                    "shipping"=>7.50,
18:                    "color"=>"red" ),
19:     "ORAC AI"      => array( "price"=>2200.50,
20:                    "shipping"=>34.50,
21:                    "color"=>"blue" ),
22:     "HAL 2000"     => array( "price"=>4500.50,
23:                    "shipping"=>18.50,
24:                    "color"=>"pink" )
25:     );
26: $dbh = dba_open( "./data/products2", "c", "gdbm" )
27:       or die( "Couldn't open database" );
28: foreach ( $products as $key => $value ) {
29:   dba_replace( $key, serialize( $value ), $dbh );
30: }
31: dba_close( $dbh );
32: ?>
33: </div>
34: </body>
35: </html>

We build a multidimensional array beginning on line 12, containing the product names as keys and four arrays of product information as values. We then open the database on line 26 and loop through the array on line 28. For each element, we pass the product name and a serialized version of the product array to dba_replace() (line 29). We then close the database (line 31).

Listing 12.5 writes the code that extracts this data.

Listing 12.5 Retrieving Serialized Data from a Database
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 12.5 Retrieving Serialized
 7:    Data from a Database</title>
 8: </head>
 9: <body>
10: <div>
11: <p>
12:   Here at the Impossible Gadget Shop
13:   we're offering the following exciting
14:   products:
15: </p>
16: <table border="1" cellpadding ="5">
17: <tr>
18: <td align="center"> <b>product</b> </td>
19: <td align="center"> <b>color</b> </td>
20: <td align="center"> <b>shipping</b> </td>
21: <td align="center"> <b>price</b> </td>
22: </tr>
23: <?php
24: $dbh = dba_open( "./data/products2", "c", "gdbm" )
25:       or die( "Couldn't open database" );
26:
27: $key = dba_firstkey( $dbh );
28: while ( $key != false ) {
29:   $prodarray = unserialize( dba_fetch( $key, $dbh) );
30: ?>
31:   <tr><td align="left">
32:     <?=$key?>
33:   </td><td align="left">
34:     <?=$prodarray['color']?>
35:   </td><td align="right">
36:     $<?=sprintf( "%01.2f", $prodarray['shipping'] )?>
37:   </td><td align="right">
38:     $<?=sprintf( "%01.2f", $prodarray['price'] )?>
39:   </td></tr>
40: <?php
41:   $key = dba_nextkey( $dbh );
42: }
43: dba_close( $dbh );
44: ?>
45: </table>
46: </div>
47: </body>
48: </html>

Listing 12.5 is similar to the example in Listing 12.3. In this case, though, we are displaying more fields. We open the database on line 24 and then use dba_firstkey() (line 27) and dba_nextkey() (line 41) to loop through each item in the database. We extract the value and use unserialize() to reconstruct the product array on line 29. Then printing each element of the product array to the browser is easy. Notice that we enter HTML mode to write the table rows. We print dynamic information using the short PHP tags in conjunction with an equals sign (=). This construction is very useful for embedding dynamic values in HTML. So


<?= $value ?>

is equivalent to


<?php
echo $value;
?>

The former fragment is nicely compact. We are assuming that short open tags are enabled, which can be risky if you expect to deploy your code on servers beyond your control.

Figure 12.2 shows the output from Listing 12.5.

Figure 12.2. Retrieving serialized data from a database.

graphics/12fig02.gif

    [ Team LiB ] Previous Section Next Section