Book Image

Building Online Stores with osCommerce: Beginner Edition

By : David Mercer
Book Image

Building Online Stores with osCommerce: Beginner Edition

By: David Mercer

Overview of this book

Using an easy-to-read and engaging style, this book introduces the fundamentals of osCommerce, and helps you build your first online store. It covers the out-of-the-box features of osCommerce, but it also shows you how to customize the application to your own needs. The book starts with the basics of downloading and installing osCommerce, or simply how to enable it on your Internet domain using the tools provided by your host. All of the most important configuration issues are explained, with clear instructions and advice to help you make the right choices. Once osCommerce is installed and configured, you will take a good look at how to work with your store's data including product information as well as other data which is responsible for keeping your site healthy. The all important topic of customization is also dealt with comprehensively. You will see how to develop attractive sites that will make your store a pleasure to browse and your products a pleasure to buy! Of course, no discussion on osCommerce would be complete without a look at how to obtain and treat payments. Using the modules provided with osCommerce you will be collecting money from your happy customers in no time! Once the reader has a fully fledged, and operational site it is time to look at deployment? an important topic for discussion if development has taken place on a development machine. The appendix will add a few tools to your armory and shed some light as to what is going on behind the scenes in case things go awry.
Table of Contents (13 chapters)

Debugging Code Yourself


Before we continue, I should mention that we will demonstrate some fairly complex debugging using the example code given in the professional version of the book. Please bear in mind that it is not important for you to have this code in order to follow along—the important thing is you appreciate the manner in which the error was detected and corrected.

Let’s begin with a couple of the easier‑to‑solve syntax problems. PHP will kick up a variety of different errors depending on where and how the syntax problem has caused an error in the script. For example, if you added a line to your code in order to perform a task (perhaps you added an extra echo statement), but get the following screen when you run the script:

Looking at this error, you can see that on line 94 of the feed.php script (don’t worry if you don’t have this particular page yourself—it is a custom page used for this demo), the PHP interpreter expects to find a, or;, but instead it has come across something called a T_VARIABLE. A T_VARIABLE is simply PHP’s name for a variable defined in your script. So the English translation of this error is:

I have come across one of your variables instead of what I expected, namely a comma or semi-colon, on line 94 of the feed.php script in the C:\Program Files\Apache Group\Apache2\htdocs\catalog directory.

If we take a look at that spot in the code, we see the following:

} else{
echo "<font face=’Verdana’ size=’2’>Previous</font>";
}
echo "</td><td align=center width=’30%’>"

$i=0;
$l=1;
for($i=0;$i < $numrows;$i=$i+$limit){

Can you see the error? We simply forgot to insert a semi-colon to finish off the echo statement so PHP didn’t realize the line had ended and ended up coming across $i unexpectedly. Adding one fixes the problem, and the script runs as normal. So far so good, but what about other types of syntax error? What can we expect to get from PHP if, for example, we miss out a brace two lines above the echo statement? Reasonably, you could assume that it should report that there is a missing brace on line 92 (since the closing brace is two lines above the echo statement from the previous example), couldn’t you?

Well, removing the closing brace from the else statement in the previous code snippet gives the following error message:

Oh dear, this is not very helpful; line 156 is the very last line of the script, and we happen to know already that it is line 92 which is causing the problem. How have things gone wrong, and what is PHP trying to tell us? The problem here lies in the fact that PHP doesn’t really know what your program does, it simply takes it for granted you know what you are doing. So when you open a brace, it will treat everything that follows as part of that code block until it finds a matching closing brace—even if this is not what you intended. In our case, there is no matching closing brace, so PHP is telling us:

I got to the end of the file, but that is unexpected because you haven’t finished your script properly.

This is where having a good PHP editor comes in. If you are using something like the Zend development environment, then the script editor is PHP-aware and can often help pinpoint problems like this because it automatically indents code so that it is a lot easier to see problems like this by simply looking at the file. Which do you think is easier to understand, this:

Or this:

As you can see, a proper editor makes life a lot easier because from this screenshot, we can see that there should be a brace inserted after the fourth visible echo statement, but before the fifth. How? Well, look at the code indenting, if the fifth echo statement was part of the else block, it would also be indented. Of course, this is slightly contrived, but you get the picture"make sure you have a reasonable code editor before you attempt any serious debugging.

What about slightly more tricky problems, such as errors in the code’s logic? Perhaps you have noticed that while no errors are being thrown up by PHP, your web page doesn’t behave as you expect. Problems like this require a slightly more sophisticated approach. Let’s say, for example, that when viewing the feed.php page in the browser, you notice that the navigation at the bottom of the page is not working properly—an example is shown here:

The above screenshot also highlights why it is so important to test everything thoroughly. Can you spot the problem? Well, the navigation links at the bottom of the feed page show that there is only one page, yet as you can clearly see, the Next button can still be activated, implying that there are more than ten items in the feed (the feed.php script is set to allow for ten results per page). This is a bit of a problem: either there are only ten items in the feed, in which case the Next button should not be active, or there are more than ten items in the feed, in which case there should be more than one page of feed items.

So what do we do in this case?—there are no fatal errors or warnings to guide us, so we are on our own. Well, luckily for us, a large part of the analysis of the problem has been done for us already, because we know how this part of the application should behave. In other words, the problem is simple to understand—this doesn’t necessarily mean it has a simple solution, but knowing what we want to achieve is an important step to rectifying any problem.

Furthermore, we have already advanced two plausible explanations for the problem. Either the Next button is not behaving properly or the pagination display is not working correctly. What’s the next step? Do we jump in and try to fix the code? Not yet; there is something else we can do to further clarify the problem. Since we have access to the database, let’s find out how many records there actually are—this will tell us whether we should have more pages than we do.

A quick visit to the MySQL command line tells us the following:

We have eleven items in the feed table, which means that the pagination display is definitely not working correctly. Do we go fix it yet? Not yet; just because the pagination display is not working, doesn’t automatically imply that the Next and Previous links are. Let’s test those quickly before we do anything. With 11 rows in the database, we expect the first page to have an inactive Previous link and an active Next link. If we click the Next link, the following page should have an active Previous link, an inactive Next link, and only one item. Trying this all out confirms that under these circumstances, the links are working correctly:

Before we go any further, there are a few considerations to point out. First of all, the pagination and links may work for the given number of items in the database. Just because they do, you shouldn’t assume that they work for any number of items. Any page should be tested with a wide variety of item quantities to ensure they work correctly. Second, if the Previous and Next links didn’t work, then there was nothing you could assume about the nature of the problem, because either there is a separate source of error for the pagination and the links, or there is a common link causing the errors in both—you can’t tell with the information you have.

Note

When debugging, try to keep your mind completely free of assumptions about the nature of the error.

OK, so we can consider the problem to be fairly well analyzed now. We understand how the code is supposed to work, and we have gathered information to help us eliminate certain possibilities as well as confirm certain suspicions. Having done all this, we should still try to keep a clear view of things, because often problems can have very unexpected or subtle causes, which are hard to find if you act predominantly on assumption. With the analysis done, we now need to begin examining the code in order to understand the nature of the problem.

This is where certain tricks come into play. Two of the most common questions a programmer needs answered are:

  • What values are being held in variables at a given point of program execution?

  • How is the program being executed?

Now, at this point it is probably worth mentioning that you can obtain something called an Integrated Development Environment (IDE) for developing and debugging code. Zend, the people who make PHP, have a development studio available, and you can look over their products at http://www.zend.com/store/products/zend-studio/. This comes with a suite of facilities to help you sort out problems like this. For example, you can expect:

  • A Code analyzer

  • Code completion

  • Syntax highlighting

  • A Project manager

  • A Code editor

  • A Graphical debugger

  • Wizards

All of these work together to help you create better code, and debug and analyze any code that you already have. If, however, you don’t feel the need to fork out cash to work on your projects, then you might want to consider something like the freely available Dev-PHP, found at http://devphp.sourceforge.net/. However, you can do a fairly useful job of discovering variable content and program execution all by yourself by employing the following methods:

  • echo variable contents to the screen

  • echo program execution markers to the screen

Let’s take a look at how this can help us to solve the feed page problem.

Knowing that we are most likely looking at a pagination display problem alone, let’s focus our efforts on seeing what is happening under the hood. Hopefully, this will reveal where the flaw is occurring so that we can modify it and solve the problem. First thing’s first, let’s find the relevant section of code:

$i=0;
$l=1;
for($i=0;$i < $numrows;$i=$numrows+$limit){
if($i <> $start){
echo " <a href=’" . tep_href_link(FILENAME_FEED) . ‘&start=’ . $i . "’><font face=’Verdana’ size=’2’>" . $l . "</font></a> ";
} else { echo " <font face=’Verdana’ size=’2’ color=’red’>$l</font> ";}
$l=$l+1;
}

This snippet is responsible for outputting the pages. The first thing we notice is that it makes use of the $numrows variable, which is declared elsewhere. Let’s go look for that declaration, so we understand what type of value it should contain. Looking up the page we find:

$find_rows = tep_db_query("select count(*) from feed;");
$numrows=mysql_result($find_rows, 0);

Ah ha! Notice that $numrows should contain the number of records in the database. Recall that earlier we used the same SQL query to determine this value. We are also making use of the $limit and $start variables, which we need to find as well. Searching earlier in the code, we find:

if(!isset($_GET[‘start’])) {
$start = 0;
}else {
$start = $_GET[‘start’];
}
$limit = 10;

From this we can see that the $start variable contains the value of $i, which is the iterator variable for the for loop, and $limit is simply the number of items to show per page. Since we are not getting the right number of pages printed out to the screen, let’s take a look at how the for loop is working in more detail. In order to do this, we want to track the values of the variables being used as well as the program execution. Accordingly, we can use a debugging modification like this:

$i=0;
$l=1;
for($i=0;$i < $numrows;$i=$numrows+$limit){
echo "We are in the for loop here: <br>";
echo ‘$i = ‘ . $i . "<br>";
echo ‘$l = ‘ . $l . "<br>";
echo ‘$numrows = ‘ . $numrows . "<br>";
echo ‘$limit = ‘ . $limit . "<br>";

if($i <> $start){
echo " We are in the if statement here: <br>";
echo ‘ $i = ‘ . $i . "<br>";
echo ‘ $l = ‘ . $l . "<br>";
echo ‘ $numrows = ‘ . $numrows . "<br>";
echo ‘ $start = ‘ . $start . "<br>";

echo " <a href=’" . tep_href_link(FILENAME_FEED) . ‘&start=’ . $i . "’><font face=’Verdana’ size=’2’>" . $l . "</font></a> ";
} else { echo " <font face=’Verdana’ size=’2’ color=’red’>$l</font> ";
echo " We are in the else block: <br>";
echo ‘ $i = ‘ . $i . "<br>";
echo ‘ $l = ‘ . $l . "<br>";
echo ‘ $numrows = ‘ . $numrows . "<br>";

$l=$l+1;
}
}

Generally, you don’t need to be quite as verbose as the above statements. If you have a fairly good idea of what is going on, you simply need to echo one or two values to the screen to find out what is happening. Looking at the results of the above modifications, we see that for the first page our results are:

Straightaway you should get the nagging suspicion that something is wrong, because we are only going through the loop once before finishing. What’s worse, our if condition never evaluates to true before the for loop ends its single iteration. The values we have outputted all seem to be in order for what we would expect for the first iteration of the for loop, so immediately we should suspect that something is wrong with the actual for loop conditions. Let’s take a closer look at them here:

for($i=0;$i < $numrows;$i=$numrows+$limit){

Agh! What a silly mistake! Looking at the for loop condition from a structural point of view, we have asked it to do the following:

  1. 1. Begin the loop with $i equal to zero.

  2. 2. Test if $i is less than $numrows.

  3. 3. If it is, then execute the code block.

  4. 4. Evaluate the final expression $i = $numrows + $limit.

  5. 5. Repeat steps 2 to 4.

From the output of our echo statements, shown in the previous figure, we can see that initially:

$numrows = 11

$limit = 10

So, when step 4 is evaluated, $i is assigned the value 21. Moving to step 5 redirects us to step 2, which asks us to test that $i (21) is less than $numrows (11), which it quite clearly isn’t, so the for loop breaks out, and we move on without performing any more actions. To be honest, this example is slightly contrived because an experienced programmer would have immediately noticed that $numrows + $limit > $numrows because $limit > 0.

For the purposes of learning how to monitor program execution, this is perfect because we noticed an unexpected result in that the for loop was only executing once. So, we need to modify the for loop so that it executes the correct number of times. In order to do this, we need to think carefully about what it is we want the loop to achieve. Effectively, we need it to take the number of items there are in the database, and divide by the record limit per page in order to decide how many pages to create. Then for each page, it needs to create a numbered link to those results, except for the current page, which is not a link.

Modifying the third condition of the for loop to the following:

for($i=0;$i < $numrows;$i=$i+$limit){

fixes the problem because whatever the value of $numrows, the for loop will iterate the correct number of times because we are increasing the value of $i by $limit each time. Trying the debugged code again gives the following results:

Looking closely at this output, you can see that there is now a 2 outputted at the bottom of the screen. This is as we would expect, because there are two pages required for eleven feed items. The for loop finishes after the first if statement (not counting the initial execution of the else block) because after that $i has a value of 20.

Finally, you can see that the second time we enter the for loop, $i has a value of 10. Because of this, we enter the if statement because $i (10) is not equal to $start (0) because we are on the first page. This means we output a link to the second page and set the value of $start to 10 by appending it to the URL of the link.