PHP Logo by Colin Viebrock released under Creative Commons Attribution-Share Alike 4.0 International License at https://www.php.net/download-logos.php

Recently for one of my classes at Wake Tech I had to develop a Web Store, as usual Wake Tech projects in general need to be written in PHP (with the exception of the ASP class where C# with Legacy Web Forms is used). With COVID-19, Social Distancing, and an upside down schedule, and increased anxiety, completing my final projects was more difficult than anticipated. This blog post goes over a few of the techniques I used and how I solved various problems in my final project for Wake Tech's eCommerce class to write easy to read PHP code while dealing with time limitations.

Time Limitations

Time was the biggest issue with developing this application as I still have to study for finals, do my other four projects, do projects for the company I work for, and balance everything with my personal life. It's been a crazy past few weeks. I decided that the best approach was to sit down for two-hour work periods on the project and to focus on keeping the code as easy to work with as possible. This worked well for reducing stress while working on the project and led to it's swift completion.

Mimicking C# Razorpages syntax...

On a day to day basis I usually write C# with the Razorpages template engine. To make my project more comfortable to work with I mimicked Razorpages syntax. I decided to use code at the top of each file rather than using code behind files to simplify things. My base template pages looked like the following code.

<?php
  $pageTitle = "Title Of Page";
  require_once('./include/config.php');
  require_once('./header.php');

  // HTTP GET Only Code
  if ($_SERVER['REQUEST_METHOD'] === 'GET')
  {
     //...
  }

  // HTTP POST Only Code
  if ($_SERVER['REQUEST_METHOD'] === 'POST')
  {
     //...
  }
?>

<div class="jumbotron">
  <h1 class="display-4">Header Text</h1>
  <p class="lead">Leading paragraph text</p>
</div>

<?php
  require_once('./footer.php');
?>

Issues with PDO for Database Access

While working on the database code I choose to use PDO due to its additional security properties. It reduces the risk of SQL Injection attacks. I don't need to use an escape string function as PDO uses a proper query builder. I noticed that numbers cannot be passed directly though. You have to pass data by reference, not by value. This means the reference to a value has to be passed by reference to the query builder. This was an annoying property of how the language functions. The solution was simple enough although it seems odd that the language can't do this for me. Maybe I've been spoiled by C# too much!

// $category = 1;
$catRef = &$category;
$stmt->bindParam(':category', $catRef);

Issues with PHP Sessions

I implemented the shopping cart as an empty array of product ids which was initially set on login.php however since guests can add things to the cart as well a bug would show up where the cart array didn't exist. I checked for a null cart as follows and initialize it on demand with the follow null check code. It works so far and I'm happy with it.

if ($_SESSION["cart"] == null)
{
  $_SESSION["cart"] = array();
}

To avoid a user passing non-existent IDs into to the array I used a database lookup to ensure the ID is valid. A drawback to this approach is that deleting an item from the admin area won't implicitly delete the ID from the array. Further checks are needed if this code is used in a production web application to remove deleted items from the cart. The finalized addtocart.php code is as follows...

<?php
  require_once('./include/config.php');

  $stmt = $conn->prepare("SELECT * FROM Products WHERE id=:id LIMIT 1");
  $stmt->bindParam(':id', $_GET["id"]);
  $stmt->execute();

  // If the user has not logged in the cart array won't exist and this can cause a bug.
  // This hotfix sets the cart to a blank array to work around this issue!
  if ($_SESSION["cart"] == null)
  {
    $_SESSION["cart"] = array();
  }

  if (count($stmt->fetchAll()) > 0)
  {
    array_push($_SESSION["cart"], $_GET["id"]);
  }

  header('Location: '.$baseUrl.'/cart.php');
  exit;
?>

Error Handling

I had to test for errors locally since the student server's configuration doesn't allow easy access to error logs. I did my best to write code that would "never encounter an error". This isn't really possible but I made a best effort to do so.

Product Research and Data Entry

This was the easiest part of my project since I took the time to code an admin area. It was just getting product names, writing a description, and finally entering a price and image url. It was a swift process and I'm happy with it. To save on time I used Lorem Ipsum text and royalty-free stock images. The images were from Pixabay a website recommended in another class I attended (I can't remember which class though!).

Final Project Source

I've published the source code to my final project on GitHub. It's available for those who want to see the full source code. It's released under the BSD 3-Clause "New" or "Revised" License.

Conclusion

It's possible to complete projects under stressful circumstances while still remaining in your comfort zone. I hope you found this post informative and that it gives you inspiration on your next PHP Project.