The Product Catalog


For customers to be able to purchase products, they'll need to view them first. To this end, I'll create two scripts for accessing the product catalog. The first, browse_prints.php, will display a list of the available prints. If a particular artist has been selected, only that artist's work will be shown; otherwise, every print will be listed.

The second script, view_print.php, will be used to display the information for a single print, including the image. On this page customers will find an Add to Cart link, so that the print may be added to the shopping cart. Because the print's image is stored outside of the Web root directory, view_print.php will use a separate scriptvery similar to download_file.php from Chapter 12, "ExampleContent Management"for the purpose of displaying the image.

Searching the Product Catalog

The structure of this database makes for a fairly easy search capability, should you desire to add it. As it stands, there are only three logical fields to use for search purposes: the print's name, its description, and the artist's last name. A LIKE query could be run on these using the following syntax:

 SELECT...WHERE prints.description LIKE  '% LIKE '%Another option would be to create an advanced search, wherein the user selects whether to search the artist's name or the print's name (similar to what the Internet Movie Database, www.imdb.com, does with people versus movie titles).

Finally, you could make use of MySQL's full-text search capability to return results in their order of relevance.


To make browse_prints.php

1.

Create a new PHP document in your text editor (Script 14.6).

 <?php # Script 13.6 - browse_prints.  php $page_title = 'Browse the Prints'; include ('./includes/header.html'); require_once ('../mysql_connect.  php); 

Script 14.6. The browse_prints.php script displays every print in the catalog or every print for a particular artist, depending upon the presence of $_GET['aid'].


2.

Build the query.

 if (isset($_GET['aid'])) {   $aid = (int) $_GET['aid'];   if ($aid > 0) {      $query = "SELECT artists.       artist_id, CONCAT_WS(' ',       first_name, middle_name,       last_name) AS name, print_       name, price, description,       print_id FROM artists, prints       WHERE artists.artist_id =       prints.artist_id AND prints.       artist_id =$aid ORDER BY       prints.print_name;   } else {      $query = "SELECT artists.       artist_id, CONCAT_WS(' ',       first_name, middle_name,       last_name) AS name, print_       name, price, description,       print_id FROM artists, prints       WHERE artists.artist_id =       prints.artist_id ORDER BY       artists.last_name ASC,       prints.print_name ASC;   } } else {   $query = "SELECT artists.    artist_id, CONCAT_WS(' ',    first_name, middle_name, last_    name) AS name, print_name,    price, description, print_id    FROM artists, prints WHERE    artists.artist_id = prints.    artist_id ORDER BY artists.    last_name ASC, prints.print_name    ASC; } 

The query is a standard join across the artists and prints tables (to retrieve the artist name information with each print's information). The first time the page is viewed, every print by every artist will be returned. If a user clicks one artist's name, the user will be returned back to this page, but now the URL will be, for example, browse_prints.php?aid=529. In that case, the clause AND prints.artist_id = $aid is added to the query and the ORDER BY is slightly modified so that just that artist's works are displayed.

So the two different roles of this scriptshowing every print or just those for an individual artistare defined by this conditional, while the rest of the script works the same in either case.

For security purposes, I use type casting on the author ID and make sure that it's a positive integer prior to using it in a query.

3.

Create the table head.

 echo '<table border="0" width="90%"  cellspacing="3 cellpadding="3"  align="center> <tr> <td align="left" width="20%">  <b>Artist</b></td> <td align="left" width="20%">  <b>Print Name</b></td> <td align="left" width="40%">  <b>Description</b></td> <td align="right" width="20%">  <b>Price</b></td> </tr>'; 

4.

Display every returned record.

 $result = mysqli_query ($dbc, $query); while ($row = mysqli_fetch_array  ($result, MYSQLI_ASSOC)) {   echo " <tr>      <td align=\"left\"><a href=\       "browse_prints. php?aid={$row['artist_id']}\">{$row  ['name]}</a></td>      <td align=\"left\"><a href=\       "view_print.php?pid={$row       ['print_id]}\">{$row       ['print_name]}</td>      <td align=\"left\">{$row       ['description]}</td>      <td align=\"right\">\${$row       ['price]}</td>   </tr>\n"; } 

I want the page to display the artist's full name, the print name, the description, and the price for each returned record. Further, the artist's name should be linked back to this page (with the artist's ID appended to the URL), and the print name should be linked to view_print.php (with the print ID appended to the URL). Figure 14.22 shows some of the resulting HTML source code.

Figure 14.22. The source code for the page reveals how the artist and print IDs are appended to the links.


Remember that if you are not using the Improved MySQL Extension functions, you'll need to change your function calls here.

5.

Close the table, the database connection, and the HTML page.

 echo '</table>'; mysqli_close($dbc); include ('./includes/footer.html'); ?> 

6.

Save the file as browse_prints.php, upload to your Web server, and test in your Web browser (Figures 14.23 and 14.24).

Figure 14.23. The current product listing, created by browse_prints.php.


Figure 14.24. If a particular artist is selected (by clicking on the artist's name), the page displays works only by that artist.


Tips

  • You could easily take the dynamically generated pull-down menu from add_print.php and use it as a navigational tool on the public side. Set the form's action attribute to browse_print.php, change the name of the pull-down menu to aid, use the get method, and when users select an artist and click Submit, they'll be taken to, for example, browse_print.php?aid=5.

  • Although I did not do so here, you could paginate the returned results using the technique described in Chapter 8, "Web Application Development" (see the view_users.php script).

  • Another feature you could add to this page is the option to choose how the prints are displayed. By adding links to the column headings (e.g., to browse_prints.php?order=price), you could change the ORDER BY in the query and therefore the resulting display. Again, this idea was demonstrated in Chapter 8.


To make view_print.php

1.

Create a new PHP document in your text editor (Script 14.7).

 <?php # Script 14.7 - view_print.php $problem = FALSE; 

Script 14.7. The view_print.php script shows the details for a particular print. It also includes a link to add the product to the customer's shopping cart.


I'll use the $problem variable to track whether or not a problem occurred on this page.

2.

Validate that a print ID has been passed to this page.

 if (isset($_GET['pid'])) { 

This script won't work if it does not receive a valid print ID, so I check for the ID's existence first.

3.

Retrieve the information from the database.

 $pid = (int) $_GET['pid']; require_once ('../mysql_connect.  php); $query = "SELECT CONCAT_WS(' ',  first_name, middle_name, last_name)  AS name, print_name, price,  description, size, image_name  FROM artists, prints WHERE artists.  artist_id = prints.artist_id AND  prints.print_id = $pid; $result = mysqli_query ($dbc, $query); 

The query is a join like the one in browse_prints.php, but it selects only the information for a particular print. I'm type-casting the print ID as an integer prior to using it in the query for security purposes (so that a malicious user doesn't try to break my query using invalid $_GET['pid'] values).

4.

If a record was returned, retrieve the information, set the page title, and include the HTML header.

 if (mysqli_num_rows($result) == 1) { $row = mysqli_fetch_array ($result,  MYSQLI_ASSOC);   $page_title = $row['print_name'];   include ('./includes/header.html'); 

The browser window's title (Figure 14.25) will be the name of the print.

Figure 14.25. The browser page title will be the name of the print being viewed (like The Birth of Venus here).


5.

Begin displaying the print information.

 echo "<div align=\"center\">   <b>{$row['print_name']}</b> by   {$row['name']}   <br />{$row['size']}   <br />\${$row['price']}   <a href=\"add_cart.php?pid=    $pid\">Add to Cart</a>   </div><br />"; 

The header for the print will be the print's name (in bold), followed by the artist's name, the size of the print, and its price. Finally, a link is displayed giving the customer the option of adding this print to the shopping cart (Figure 14.26). The shopping cart link is to the add_cart.php script, passing it the print ID.

Figure 14.26. The print information and a link to buy it are displayed at the top of the page.


6.

Display the image and description.

 if ($image = @getimagesize  ("../uploads/{$row['image_name]  }")) {   echo "<div align=\"center\">    <img src=\"show_image.php?    image={$row['image_name]}\"    $image[3] alt=\"{$row    ['print_name]}\" />"; } else {   echo "<div align=\"center\">No    image available."; } echo "<br />{$row['description']}  </div>"; 

This section of the script will first attempt to retrieve the image's dimensions by using the getimagesize() function. If it is successful in doing so, the image itself will be displayed. This process is a little unusual in that the source for the image calls the show_image.php page. This script, to be written next, retrieves and displays the $_GET['image'] passed to it.

If the script could not retrieve the image information (because the image is not on the server or no image was uploaded), a message is displayed instead.

Finally, the print's description is added (Figure 14.27).

Figure 14.27. The print's image followed by its description.


7.

Complete the two main conditionals.

   } else {      $problem = TRUE;   }   mysqli_close($dbc); } else {   $problem = TRUE; } 

The first else clause is in case one record is not returned by the query. The second is in case no print ID is passed to this page. Under both circumstances the $problem variable is set to TRUE, which will be used by the script in the next step.

8.

If a problem occurred, display an error message,

 if ($problem) {   $page_title = 'Error';   include ('./includes/header.html');   echo '<div align="center">    This page has been accessed in    error!</div>'; } 

If the print's information could not be retrieved from the database for whatever reason, an error should be displayed. Because the HTML header would not have already been included if a problem occurred, it must be included here first.

9.

Complete the page.

 include ('./includes/footer.html'); ?> 

10.

Save the file as view_print.php and upload to your Web server.

Tips

  • Many e-commerce sites use an image for the Add to Cart link. To do so in this example, replace the text Add to Cart (within the <a> link tag) with the code for the image to be used. The important consideration is that the add_cart.php page gets passed the product ID number.

  • If you want to show the availability of a product, add an in_stock field to the prints table. Then display an Add to Cart link or Product Currently Out of Stock message according to the value in this column for that print.

  • Depending upon the Magic Quotessetting of your PHP installation, you may or may not need to make use of the stripslashes() function when displaying the print information in this and the previous script.


To write show_image.php

1.

Create a new PHP document in your text editor (Script 14.8).

 <?php # Script 14.8 - show_image.php 

Script 14.8. This script is called by view_print.php (Script 14.7) and displays the image stored in the uploads directory.


2.

Check for an image name.

 if (isset($_GET['image'])) { 

Before continuing, I want to ensure that the script received a valid image name, which should be part of the HTML src attribute for each print (Figure 14.28) in view_print.php.

Figure 14.28. The HTML source of the view_print.php page shows how the src attribute of the img tag calls the show_image.php script.


3.

Check that the image is a file on the server.

 $image = "../uploads/{$_GET  ['image]}"; if (file_exists ($image) && (is_file  ($image))) {   $name = $_GET['image']; 

Before attempting to send the image to the Web browser, I want to make sure that it exists and that it is a file (as opposed to a directory). If so, I create a new variable called $name that will be used when the image is sent to the Web browser.

As a security measure, I hard-code the image's full path as a combination of ../uploads and the received image name. Even if someone were to attempt to use this page to see /path/to/secret/file, this script would look for ../uploads//path/to/secret/file (including the double-slash), which is safe. You could also validate the MIME type (image/jpg, image/gif) of the file here.

4.

Complete the two validation conditionals.

   } else {     $image = './images/unavailable.      gif;     $name = 'unavailable.gif';   } } else {   $image = './images/unavailable.    gif;   $name = 'unavailable.gif'; } 

If the image doesn't exist or isn't a file, the first else clause comes into effect. If no image name was passed to this script, the second else clause applies. In either case, a default image will be used (Figure 14.29).

Figure 14.29. If the page cannot access a valid print image, this default image will be displayed.


5.

Retrieve the image information.

 $ft = mime_content_type($image); $fs = filesize($image); 

To download the file, I'll need to know the file's type and size. I retrieve this information using the mime_content_type() and filesize() functions. The first one was added in PHP 4.3 but needs to be enabled on Windows in order to work.

6.

Send the file.

 header ("Content-Type: $ft\n"); header ("Content-disposition:  inline; filename=\"$name\"\n); header ("Content-Length: $fs\n"); readfile ($image); 

These header() calls will send the file data to the Web browser, much as they did in Chapter 12. The key difference between that example and this one is that the Content-disposition is now set as inline, as opposed to attachment. Because of this distinction, the sent file (the image) will be displayed in the browser, whereas previously the browser was prompted to download the file to the user's computer.

To revisit the overall syntax, the first line prepares the browser to receive the file, based upon the MIME type. The second line sets the name of the file being sent.

The last header() function indicates how much data is to be expected. The file data itself is sent using the readfile() function, which reads in a file and immediately sends the content to the Web browser.

7.

Complete the page.

 ?> 

Notice that this page contains no HTML. It only sends an image file to the Web browser.

8.

Save the file as show_image.php, upload to your Web server, and test in your Web browser by viewing any print (Figure 14.30).

Figure 14.30. The view_print.php page, where the print's image is retrieved and shown thanks to show_image.php.


Tip

  • If the view_print.php page does not show the image for some reason, you'll need to debug the problem by running the show_image.php directly in your Web browser. View the HTML source of view_print.php and find the value of the img tag's src attribute. Then use this as your URL (in other words, go to http://localhost/show_image.php?image=BirthOfVenus.jpeg). If an error occurred, running show_image.php is the best way to find it.




    PHP and MySQL for Dynamic Web Sites. Visual QuickPro Guide
    PHP and MySQL for Dynamic Web Sites: Visual QuickPro Guide (2nd Edition)
    ISBN: 0321336577
    EAN: 2147483647
    Year: 2005
    Pages: 166
    Authors: Larry Ullman

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net