Tuesday, 3 May 2011

Admin - View Category

All the product categories for the online shop are listed here. The sql
query for it is pretty simple. We just select category id, parent id and name
and using a while loop we show the category one
by one.

Below is the screenshot for the category list page. You ca see that on each
row there's a Modify link and Delete link. Clicking on the Modify link will
take you to the category modification page ( admin/category/modify.php
) where you can update the category name, description and image. Clicking
on the Delete link will pop a javascript confirmation box asking whether you
are sure to delete the category. Using a confirmation is a must when you want
to delete something. This will prevent stupid accident where you unknowingly
click on the delete link and suddenly the category disappear before you even
realize what's going on.

 

Online Shop Admin - View Category

Take a look at the code snippet below :

Source code : admin/category/list.php

<?php
// ...
$catId = (isset($_GET['catId']) && (int)$_GET['catId'] >= 0) ?
(int)$_GET['catId'] : 0;
//...
?>


When the page loads we check for the existence of catId ( category id )
in the query string. This category id is then used as the paramater for the
javascript function addCategory() . When you
click on the 'Add Category' button the parent id will be sent to category/add.php.

Go look at the source code and scroll to the bottom you will see this code
:

Source code : admin/category/list.php

<input name="btnAddCategory" type="button" id="btnAddCategory" 
value="Add Category" class="box"
onClick="addCategory(<?php echo $catId; ?>)">

 

The addCategory() function is defined in admin/library/category.js.
It simply perform a redirect to show the add category page. More
detail on adding a category can be found on the next page.

Admin Login

All user account is saved in tbl_user. For
simplicity the table will only contain the bare necessities such as user id
and password. You can add more column if you want to.

This is how the login works

  1. The admin enter it's username and password
  2. The script check whether that username and password combination do exist
    in the database
  3. If it is set the session then go the admin main page
  4. If it's not then show an error message

Below is the login page screenshot :

Onlin Shop Admin - Login

The default user name and password are "admin" ( without the quotes )








The login function is called doLogin() and
it's located in admin/library/functions.php

Source code : admin/library/functions.php

function doLogin()

{

   // if we found an error save the error message in this variable

   $errorMessage = '';



   $userName = $_POST['txtUserName'];

   $password = $_POST['txtPassword'];



   // first, make sure the username & password are
not empty

   if ($userName == '') {

      $errorMessage = 'You must enter your username';

   } else if ($password == '') {

      $errorMessage = 'You must enter the password';

   } else {

      // check the database and see if the username
and

      // password combo do match

      $sql = "SELECT user_id

                 
FROM tbl_user

                 
WHERE user_name = '$userName' AND

                 
            user_password = PASSWORD('$password')";

      $result = dbQuery($sql);



      if (dbNumRows($result) == 1) {

            $row = dbFetchAssoc($result);

            $_SESSION['plaincart_user_id']
= $row['user_id'];




            // log the time when
the user last login

            $sql = "UPDATE
tbl_user

                 
      SET user_last_login = NOW()

                 
      WHERE user_id = '{$row['user_id']}'";

            dbQuery($sql);

            // now that the
user is verified we move on to the next page

            // if the user had
been in the admin pages before we move to

            // the last page
visited

            if (isset($_SESSION['login_return_url']))
{

              header('Location:
' . $_SESSION['login_return_url']);


              exit;

            } else {

              header('Location:
index.php');


              exit;

            }

      } else {

            $errorMessage =
'Wrong username or password';

      }



  }



  return $errorMessage;

}

If the login is successful this function will set the session variable $_SESSION['plaincart_user_id'].
All admin pages will check for this session id using the checkUser()
function. If the session id is not found then the function will set a redirection
to the login page.


The checkUser() function look like this :

Source code : admin/library/functions.php

function checkUser()

{

   if (!isset($_SESSION['plaincart_user_id'])) {

      header('Location: ' . WEB_ROOT . 'admin/login.php');

   }



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

      doLogout();

   }

}

You see that if $_SESSION['plaincart_user_id']
is not set we just redirect to the login page. Very simple right?

Another thing that this function check is if there's a 'logout'
in the query string. If it is then we call the doLogout()
function which will remove the session id.

Source code : admin/library/functions.php

function doLogout()

{

   if (isset($_SESSION['plaincart_user_id'])) {

      unset($_SESSION['plaincart_user_id']);

      session_unregister('plaincart_user_id');

   }



   header('Location: login.php');

}

Next we start making the category
pages

Admin Control Panel

Our shopping cart admin page consist of the following :
  • Category
    • Add Category

      Add a new category.



    • View Category

      List all the category we have. We can also see all
      the child categories and show many products in each
      category



    • Modify Category

      Update a category information, the name, description
      and image



    • Delete Category

      Remove a category. All products in it will be set
      to have cat_id = 0.



  • Product
    • Add Product

      Insert an item into our store. We also need to supply
      the product image and we'll create a thumbnail automatically
      from this image



    • View Product

      View all the products we have. Since our online shop
      can have many products we can view the products grouped
      by category.



    • Modify Product

      Modify product information. We can also remove the
      product image from this page



    • Delete Product

      Remove a product from the shop



  • Order
    • View Orders

      Here we can see all the orders we have and their status.
      When you click the "Order" link on the left
      navigation you will go straight to the "Paid"
      orders. The reason is so you can respond immediately
      upon your customers that already paid for their purchase.




    • Modify Orders

      Sometimes a customer might contact us saying that
      she made the wrong order like specifying the wrong
      product quantity or simply want her order cancelled
      so she can repeat the buying process again. This page
      enables the admin to do such a thing.



  • Shop Configuration

    This is where we can set and change our online shop appearance,
    behaviour and information ( like the shop name, main url,
    etc ).




Below is what admin main page ( admin/index.php ) look like.
Online Shop Main Admin Page




By the way the shopping cart name is PlainCart :-)
Each sub-module (category, product, etc) will have similar file structure.
They are :
  • index.php
  • list.php
  • add.php
  • modify.php
  • process<sub-module name>.php
The admin/index.php only serves as a simple display
when the admin enters the administrator section. On this page
(and all other pages in the admin sections ) we check if the one
requesting the file is already logged in or not. This way we can
be sure that anyone who plays around with the admin pages are
those who have the required permission.
All admin pages will be using the same template so they will all
look alike. Basically each admin file will set the page title,
what javascript to include and the main content. If you want to
customize the look of the admin pages you only need to modify
the template and the css file ( admin.css ) . Here is the code
for template.php
Source code : admin/include/template.php
<?php

if (!defined('WEB_ROOT')) {

   exit;

}

$self = WEB_ROOT . 'admin/index.php';

?>

<html>

<head>

<title><?php echo $pageTitle; ?></title>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<link href="<?php echo WEB_ROOT;?>admin/include/admin.css" rel="stylesheet" type="text/css">

<script language="JavaScript" type="text/javascript" src="<?php echo WEB_ROOT;?>library/common.js"></script>

<?php

$n = count($script);

for ($i = 0; $i < $n; $i++) {

if ($script[$i] != '') {

echo '<script language="JavaScript" type="text/javascript" src="' . WEB_ROOT. 'admin/library/' . $script[$i]. '"></script>';

}

}

?>

</head>

<body>

<table width="750" border="0" align="center" cellpadding="0" cellspacing="1" class="graybox">

<tr>

<td colspan="2"><img src="<?php echo WEB_ROOT; ?>admin/include/banner-top.gif" width="750" height="75"></td>

</tr>

<tr>

<td width="150" valign="top" class="navArea"><p>&nbsp;</p>

<a href="<?php echo WEB_ROOT; ?>admin/" class="leftnav">Home</a>

<a href="<?php echo WEB_ROOT; ?>admin/category/" class="leftnav">Category</a>

<a href="<?php echo WEB_ROOT; ?>admin/product/" class="leftnav">Product</a>

<a href="<?php echo WEB_ROOT; ?>admin/order/?status=New" class="leftnav">Order</a>

<a href="<?php echo WEB_ROOT; ?>admin/config/" class="leftnav">Shop Config</a>

<a href="<?php echo WEB_ROOT; ?>admin/user/" class="leftnav">User</a>

<a href="<?php echo $self; ?>?logout" class="leftnav">Logout</a>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p></td>

<td width="600" valign="top" class="contentArea"><table width="100%" border="0" cellspacing="0" cellpadding="20">

<tr>

<td>

<?php

require_once $content;

?>

</td>

</tr>

</table></td>

</tr>

</table>

<p>&nbsp;</p>

<p align="center">Copyright &copy; 2005 - <?php echo date('Y'); ?> <a href="http://www.phpwebcommerce.com"> www.phpwebcommerce.com</a></p>

</body>

</html>

You see the bolded section on the top? All file that is meant to be included
from another file will have this right at the beginning of the code. So if
we request the file directly like this : plaincart/admin/include/template.php
it won't display anything.
But first, we have to postpone making the admin pages and create the login
page first. Because a shop admin certainly must login before doing anything
to the shop.
NOTE : When you play with the admin pages demo you will see that any changes you make doesn't have any effect at all. This is because i've commented some of the code in the demo. I do this just to make sure all the settings, products, and categories stay the same. The code for download, however, are not commented. So when you install it on your server you can make any changes as you wish

Shopping Cart Database Design

shopping-cart-database-designThe database design for our shopping cart is quite simple.
Below is the summary of what tables we need for this shopping cart plus the
short description of each table. You can see the complete SQL needed to build
the database here
Table Name Description
tbl_category Storing all product categories
tbl_product The products ( what else )
tbl_cart When the shopper decided to put an item into the shopping cart we'll
add the item here
tbl_order This is where we save all orders
tbl_order_item The items ordered
tbl_user Store all shop admin user account
tbl_shop_config Contain the shop configuration like name, address, phone number, email,
etc

The ER ( Entity Relationship ) diagram is shown below.
Shopping Cart ER Diagram




Now, let's take a better look at each table

tbl_category

This table store the product categories. From the ER diagram you can see
that our current database design enables a category to have a child category
and for the child category to have another child category and so on. But for
this tutorial we make a restriction that the category will only two level
deep like this "Top Category > Manga > Naruto". The reason
is to reduce the number of clicks required by a visitor when browsing a category.

Another rule is that a product can only be added on the second level category.
For example if we have this category structure :
Top Category > Manga > Naruto
then we can only add a product in "Naruto", not in "Manga".
The top level categories will not contain any products and a product can only
belong to one category.

 

tbl_product

In this table we store the product's name, category id, description, image
and thumbnail. For now a product can only have one image. It may not be enough
if you want to show a picture of you product from multiple angles so i plan
to improve this on future version.
When adding a product image in the admin page we don't need to upload the
thumbnail too. The script will generate the thumbnail from the main image.
The thumbnail size is defined in library/config.php
( THUMBNAIL_WIDTH ) and currently it is set to 75 pixels.
 

tbl_cart

This table will store all items currently put by the customer. Here we have
ct_session_id to save the id of a shopping session. We will explore this further
when adding a product to shopping cart

 

tbl_order

Finally when the customer finally place the order, we add the new order
in this table. The shipping and payment information that the customer provided
during checkout are alos saved in this table including the shipping cost.

For the order id i decided to use an auto increment number starting from
1001.
Why start at 1001 ?
Because an order id looks ugly ( at least for me ^^ ) if it' s too short
like 1, 2 or 3 so starting the order id from 1001 seems to be a good idea
for me.
To make the order id start from 1001 we use the following sql :

CREATE TABLE tbl_order (

   id int(10) unsigned NOT NULL auto_increment,

   date datetime default NULL,

   last_update datetime NOT NULL default '0000-00-00
00:00:00',

   status enum('New', 'Paid', 'Shipped','Completed','Cancelled')
NOT NULL default 'New',

   memo varchar(255) NOT NULL default '',

   shipping_first_name varchar(50) NOT NULL default
'',

   shipping_last_name varchar(50) NOT NULL default
'',

   shipping_address1 varchar(100) NOT NULL default
'',

   shipping_address2 varchar(100) NOT NULL default
'',

   shipping_phone varchar(32) NOT NULL default '',

   shipping_city varchar(100) NOT NULL default '',

   shipping_state varchar(32) NOT NULL default '',

   shipping_postal_code varchar(10) NOT NULL default
'',

   shipping_cost decimal(5,2) default '0.00',

   payment_first_name varchar(50) NOT NULL default
'',

   payment_last_name varchar(50) NOT NULL default
'',

   payment_address1 varchar(100) NOT NULL default
'',

   payment_address2 varchar(100) NOT NULL default
'',

   payment_phone varchar(32) NOT NULL default '',

   payment_city varchar(100) NOT NULL default '',

   payment_state varchar(32) NOT NULL default '',

   payment_postal_code varchar(10) NOT NULL default
'',

   PRIMARY KEY (   id)

) TYPE=MyISAM AUTO_INCREMENT=1001 ;

You see, we just need to add AUTO_INCREMENT = 1001
right after the create definition.

 

tbl_order_item

All ordered items are put here. We simply copy the items from the cart table
when the customer place the order.

tbl_shop_config

This table store the shop information. For now it only have the shop name,
address, phone number, contact email address, shipping cost, the currency
used in the shop and a flag whether we want to receive an email whenever a customer place an order.

tbl_user

This table save all the user or admin account. Currently all user
is an admin and all can do everything to the shop. I'm planning
to add permission level so one admin can do everything, while
the other user can only add / update product, manage orders, etc.
By the way, we will be using indexes on the tables to speed up queries.
As a matter of fact whatever application you make using indexes is a good
idea because it can improve the database query performance.

Okay, next we talk about the database abstraction. It's not a difficult
stuff so you can skim read it if you like.

Shopping Cart Tutorial Introduction

The online shop we're makin here is a basic one without any sophisticated
features and stuff. The shop has admin pages ( where the shop admin can create
categories, add products, etc ) and the shopper pages ( a.k.a the shop itself
) where all the shopping process takes place. You will learn more about them
in subsequent pages.

By the way, i did call this tutorial as a shopping cart tutorial
but actually we're building an online shop ( a really simple
one ). The shopping cart is just part of the shop. But because the
term 'shopping cart' is already common to define an online
shop solution
i just use it instead of naming this site a 'PHP MySQL
Online Shop Tutorial'.

I have to assume that you already know about PHP and MySQL so i won't explain
every code in detail. The codes are not too complicated though, i'm sure you
can understand it. I suggest you download
the code
first so you can run it on your computer. That way it's easier
for you to understand this tutorial

If you don't want to download the code that's fine but make sure you take
a look at the demo site,
this is what our shopping cart willl look like.

After you browse around you will see that the basic flow of our shop is
:

  1. A customer visit the site
  2. She browse the pages, clicking her way between categories
  3. View the product details that she found interesting
  4. Add products to shopping cart
  5. Checkout ( entering the shipping address, payment info )
  6. Leave ( hopefully to return another time )

Nothing complex here. The customer doesn't need to register for an account.
She just buy then leave.


 

Features

Okay, here are the shop features ( or maybe i should call this restrictions
)

  1. Flat shipping cost.

    No complex shipping calculation for this shop right now and i don't have
    any plan to change this in near future.



  2. Payment options including COD ( cash on delivery ) and Paypal

    For now this shop can only handle COD and payment through Paypal IPN.
    The reason i pick paypal is because they provide excellent
    resource for developers so i can test the payment process
    easily.



  3. Configurable image and thumbnail size

    You can restrict the product image width from the config
    file
    . You can also set the thumbnail width you want for
    all product images that you upload.

 

 

File
Organization

The files in our shop will be organized like this :

Shopping Cart File Organization

The plaincart/library directory contain :

  • config.php : this is the main configuration file for our shop
  • category-functions.php :functions required for fetching the categories
  • product-functions.php : contain product related functions
  • cart-functions.php : shopping cart specific functions
  • checkout-functions.php : checkout processes are in here
  • common.php : common functions required for the shop and admin pages
  • database.php : contain the database abstraction functions

The plaincart/include contain :

  • header.php

    The shop common header.



  • top.php

    You can place your shop banner here.



  • footer.php

    Common footer, display the shop address, phone number and
    email. You can add more information here when needed.



  • shop.css

    Style sheet file for our shop



  • leftNav.php

    The left navigation you see on the shop



  • categoryList.php

    Show the top categories we have



  • productList.php

    Show the products in certain category



  • productDetail.php

    You know what this is for, right ?



  • miniCart.php

    Shown on the right portion of the shop pages, it shows the
    products in the shoping cart.



  • shippingAndPaymentInfo.php

    The form to enter shipping and payment info ( step 1 of checkout
    )



  • checkoutConfirmation.php

    Show the order items, shipping & payment info ( step 2
    of checkout )



The plaincart/include/paypal directory contain
:

  • paypal.inc.php

    The configuration file for the paypal payment module



  • ipn.php

    The script that process payment verification



  • payment.php

    Contain the form that submit the payment information from
    this website to paypal website

The plaincart/admin folder will contain all the
admin files.You can see that admin folder also contain include
and library folder. These will contain specific library files
for the admin pages

All images required in our shop will be put in plaincart/images
directory. The category and product images are put in the category
and product sub-folder respectively.

 

The Requirements

For this tutorial i'm using these :

  • Apache 2
  • PHP 4.3.10 with GD ( graphics library ) support ( you can also use lower
    version but >= 4.3.7 )
  • MySQL 4

If you don't have these ready check out this tutorial to install them :
Installing
Apache PHP & MySQL

 


What Configurations You Will Need

Database Configuration

When you install the shopping cart script you will need to modify
library/config.php.
You need to change the database connection info ( database host, username, password and name ) according to your own configurations.

Enabling GD Support

The next thing you may need to do is to enable the GD support. This is usually
enabled by default by web hosting company but in case you test it on your
own computer you may need to enable it manually.

First, open the php.ini file using a text editor ( notepad is okay ) and
search for this line of code :

extension=php_gd2.dll

If you see that code preceded by a semicolon ( ; )
that means GD library is not enabled yet. Remove the semicolon to enable
GD and then restart the web server ( apache ) for the changes to take effect.


I really hope this shopping cart tutorial is useful for you. Now to take
the first step, let's start with the database
design