OsCommerce is an Open Source electronic commerce solution written in PHP/MySQL, that allows anyone with a web server to set up an online store. It’s by far the most popular shopping cart software around; many a site utilizes osCommerce for their catalog and e-commerce needs.
This document outlines the use of PHP in osCommerce by getting under the application’s hood. We will be looking at many of the issues beginning PHP programmers run into when working with osCommerce, as well as discussing the application’s basic file structure. In the end, this document will show you how to apply templates to your own osCommerce sites, and how to write your own modules using the application’s API.

For this document we will be using osCommerce 2.2 Milestone 2, available at the osCommerce website: http://www.oscommerce.com/. As of this writing, there is a fork of osCommerce available known as CreLoaded, which greatly simplifies the application of templates. CreLoaded is available at http://creloaded.com/index.php.

Also, while not absolutely necessary, the use of a robust IDE, such as Eclipse (http://www.eclipse.org/) is encouraged. I know there are a lot of die-hard developers who insist that they will ever use anything other than notepad or somesuch similar simple text-editing software, but some of the features are a good idea, such as syntax highlighting, bracket-matching, organization of projects into files and folders, and the ability to search project-wide for a bit of text (as opposed to file-by-file), will greatly aid you in your osCommerce development career. Eclipse has all of this, and is free and Open Source (like osCommerce)–and there’s a robust PHP plugin that will encourage quick and healthy development.

Understanding OsCommerce PHP

There are features of the PHP language used in the osCommerce source code that often baffle novice PHP developers. On first glance, the code looks very cluttered and dense; however, experience with the application reveals that the software conforms to a fairly simple structure.

Complex strings

A complex string may be defined as a bit of text that features concatenation, functions and other variables. Look, for example, at this line of code:

$url = HTTPS_SERVER . substr($url, strlen(HTTP_SERVER));

This line constructs a string that will be used as a URL. The uppercase items are constants (more on those a bit later); the $url variable itself has been passed into this line as part of the arguments to a function (this function is called tep_redirect(), and it’s used to redirect users to the URL passed to it in the arguments). What this line basically does is convert, via the substr () function (a PHP function used to replace specified characters in a string with other characters) a non-SSL URL to an SSL-URL. SSL stands for Secure Sockets Layer; it’s a web protocol that ensures that all traffic between the client and the server is encrypted for security purposes. It is also important to know how  net cms before anything else.

The key to understanding complex strings in PHP is the concatenation operator (the .). This operator basically glues strings together to create new strings; the elements that can be glued together can come from many sources, including variables, values returned from functions, and constants. The concatenation operator in this example glues constants and the return value from the substr() function to create a new $url string.

Constants

Constants live up to their name by remaining, um, constant. These are values in a script that are assumed will stay the same, and will not be overwritten by any other value. OsCommerce makes extensive use of constants; the above example of a complex string used constants to construct a URL string.

Most of the text in OsCommerce is controlled by constants defined in the application’s language files. For example, in the file includes/languages/english/index.php, we find:

define(‘HEADING_TITLE’, ‘Let\’s See What We Have Here’);

This is how one creates and initializes a constant via use of the define() function. Here, a constant called HEADING_TITLE is made available with the value “Let’s See What We Have Here” (note that in the line above, the \ before the ‘s’ is an escape character; it enables the value to use an apostrophe, which would, unescaped, confuse the PHP parser because the constant value is defined with single quotes).

Convention regarding constants is that they’re written in uppercase; you can use lowercase, but if you do you risk confusing yourself.

HEADING_TITLE is used in the catalog’s root directory in the corresponding index.php like so:

When processed by the application and viewed through a browser, this will output an HTML table heading that reads, “Let’s See What We Have Here”.

Complex Operations and Complex Strings

Complex operations in osCommerce are PHP expressions compounded to create a certain condition. Take, for example, this snippet of code:

if (isset($cPath) amp; amp; tep_not_null($cPath)) {

This is the beginning of a conditional block that executes based on whether or not the variable $cPath is available. isset() is a native PHP function that determines whether a certain variable exists; tep_not_null() is an osCommerce function that determines whether a variable contains anything other than the value NULL. In computer programming, NULL is a special value that roughly translates into “nothing” or “no value” (on some platforms this is not quite the same as the integer zero). These two expressions are joined in the conditional block as the condition to be met by the logical AND operator ( amp; amp;). The expression evaluates to true if both the statements evaluate to true; that is, if $cPath is set and if $cPath has a value other than nothing.

A more complex example, and a fine specimen of a complex operation, would be this line of code, from includes/application_top.php (around line 76):

if ( (GZIP_COMPRESSION == ‘true’) amp; amp; ($ext_zlib_loaded = extension_loaded(‘zlib’)) amp; amp; (PHP_VERSION gt;= ‘4’) ) {

if (($ini_zlib_output_compression = (int)ini_get(‘zlib.output_compression’)) lt; 1) {

if (PHP_VERSION gt;= ‘4.0.4’) {

ob_start(‘ob_gzhandler’);

} else {

include(DIR_WS_FUNCTIONS . ‘gzip_compression.php’);

ob_start();

ob_implicit_flush();

}

} else {

ini_set(‘zlib.output_compression_level’, GZIP_LEVEL);

}

}

If this code looks like gibberish to you, don’t panic: it’s really quite simple, if you keep in mind what complex strings are, what constants are (and what they look like in osCommerce), and that complex expressions in PHP can be built using logical operators.

The block is a series of smaller, cascaded if/else blocks. Since convention dictates that constants be written in uppercase, the first clues to understanding what this code does lie in the first conditional expression being evaluated-

(GZIP_COMPRESSION == ‘true’) amp; amp; ($ext_zlib_loaded = extension_loaded(‘zlib’)) amp; amp; (PHP_VERSION gt;= ‘4’)

-lie in the uppercase GZIP_COMPRESSION. This is obviously a constant (in this case, a configuration value retrieved from osCommerce’s configuration database table); the variable refers to whether or not gzip compression exists on the host server. Gzip is the compression algorithm behind all of those .zip files you see; if gzip rersides on the host server, the application is able to create zip files dynamically (this is convenient if your web site sells software, or any other downloadable product).

PHP needs the Zlib extension compiled into the parsing engine in order to dynamically zip files up; this is exactly what the next statement in the conditional evaluates:

$ext_zlib_loaded = extension_loaded(‘zlib’)

This line invokes the native PHP function extension_loaded() to find out if the host server has the zlib extension compiled into its PHP module. The zlib extension is used for data compression, and is needed by the gzip application. This, coupled with the GZIP_COMPRESSION constant being set to true, allows the parser to move to the next statement in this expression:

amp; amp; (PHP_VERSION gt;= ‘4’)

This checks to see which version of the PHP Language we’re working with by checking the value of the PHP_VERSION constant, another value read in from the configuration database table. These checks determine whether certain functions relating to dynamically zipping up files are available; the version check, using comparison operators, check to see if we’re working with PHP 4 or higher.

Once these checks have evaluated to true, our parser moves on to the next line of code: the beginning of another conditional block:

if (($ini_zlib_output_compression = (int)ini_get(‘zlib.output_compression’)) lt; 1) {

This checks the levels of compression the zlib extension has set for compressing zip files. It checks the $ini_zlib_output_compression variable against a casted value returned from the native PHP function ini_get(), which returns php.ini values. A cast is a way to convert one datatype to another; for example, if you have a string returned from some function, and need an integer instead (if, say, you needed to feed this value to a function that takes only integers as arguments). This cast happens because of the (int) in front of the call to ini_get(); the retun value of ini_get() will be converted to an integer, in order to compare it to the integer value stored in $ini_zlib_output_compression variable.

This compound expression asks if the $ini_zlib_output_compression variable is equal to the php.ini value corresponding to zlib.output_compression, and, if so, whether this value is greater than 1. If all of this evaluates to true, and if the PHP version is greater than PHP 4.0.4 (note the next conditional―another version check to see if certain functions are available to us), output buffering is started:

ob_start(‘ob_gzhandler’);

Output buffering is a fairly complex topic in PHP, so we won’t get too far into it here. It’s a method by which PHP builds your HTML page; if buffering is present, the page is processed and assembled before it is output to the browser; if not, the page is output as its processed. Output buffering is a trick to cut down on the time it take your page to load; one can buffer bits of HTML or even whole pages, so that they’re basically stored in an internal cache and ready to output when you want them to. It’s also a handy trick to dispel those pesky “Headers already sent” errors that can occur…

If we’re using a version of PHP older that 4.0.4, osCommerce is still able to use output buffering. Note the else statement attached to the conditional block checking if we’re using a verion above 4.0.4:

include(DIR_WS_FUNCTIONS . ‘gzip_compression.php’);

ob_start();

ob_implicit_flush();

This line illustrates how osCommerce includes files. application_top.php has a statement on or around line 31:

require(‘includes/configure.php’);

If you’re familiar with PHP, you know what the require() function does: it includes the code in the file referenced in the function’s argument. In this case, it includes includes/configure.php, a file that defines many of the basic configuration values your installation of osCommerce uses. Information about your database and your host server are found here, as well as a set of very important constants:

define(‘DIR_WS_IMAGES’, ‘images/’);

define(‘DIR_WS_ICONS’, DIR_WS_IMAGES . ‘icons/’);

define(‘DIR_WS_INCLUDES’, ‘includes/’);

define(‘DIR_WS_BOXES’, DIR_WS_INCLUDES . ‘boxes/’);

define(‘DIR_WS_FUNCTIONS’, DIR_WS_INCLUDES . ‘functions/’);

define(‘DIR_WS_CLASSES’, DIR_WS_INCLUDES . ‘classes/’);

define(‘DIR_WS_MODULES’, DIR_WS_INCLUDES . ‘modules/’);

define(‘DIR_WS_LANGUAGES’, DIR_WS_INCLUDES . ‘languages/’);

One of those constants look a bit familiar? DIR_WS_FUNCTIONS holds a string corresponding to the web server path (osCommerce distinguishes between two types of file paths: file server, which is the path viewed in terms of an actual file system, and web server, which looks at the paths as they would be served up by a host. The WS in this constant stands for web server, which means the path is a web server path) to the functions directory in your installation. The functions directory is within the includes directory; thus, assembled from the constants before it, the value is

DIR_WS_INCLUDES . ‘functions/’

application_top.php includes the file gzip_compression.php if our version of PHP is older than 4.0.4. This file basically acts as a wrapper for functions that simulate higher functions that would be available if we were using a more recent version of PHP; it enables us to use output buffering even if we have an old version of the language installed.

The end of the output buffering block in application_top.php is the else statement corresponding to the $ini_zlib_output_compression variable check. If the value from php.ini doesn’t match the variable, and we’re using a very old version of PHP (perhaps the prehistoric PHP 3), osCommerce ensures the level we have stored in our configuration database table becomes the php.ini value by using the native PHP function ini_set():

ini_set(‘zlib.output_compression_level’, GZIP_LEVEL);

ini_set() is able to write certain PHP configuration values for the duration of the script (a great function to know if your host doesn’t allow you to edit your php.ini file). In this case, the php.ini configuration value zlib.output_compression_level will be overwritten with the value of the constant GZIP_LEVEL, which is read in from the configuration table in the database. This configuration value can be set via the osCommerce administration module.

LEAVE A REPLY

Please enter your comment!
Please enter your name here