Welcome to a tutorial on how to create a simple bidding (or auction) system in PHP and MYSQL. Want to auction off some products on your website like eBay? Or want to open jobs for bidding? Well, let us walk through an example in this guide – Read on!
TABLE OF CONTENTS
DOWNLOAD & NOTES
Here is the download link to the example code, so you don’t have to copy-paste everything.
EXAMPLE CODE DOWNLOAD
Just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
SORRY FOR THE ADS...
But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.
Buy Me A Coffee Code Boxx eBooks
AUCTION & BIDDING WITH PHP MYSQL
All right, let us now get into the mechanics of an auction and bidding system in PHP MYSQL.
STEP 1) DATABASE TABLES
1A) AUCTION ITEMS
-- (A) AUCTION ITEMS
CREATE TABLE `auction_items` (
`item_id` bigint(20) NOT NULL,
`item_name` varchar(255) NOT NULL,
`item_img` varchar(255) DEFAULT NULL,
`item_desc` text DEFAULT NULL,
`bid_end` datetime DEFAULT NULL,
`bid_min` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `auction_items`
ADD PRIMARY KEY (`item_id`);
ALTER TABLE `auction_items`
MODIFY `item_id` bigint(20) NOT NULL AUTO_INCREMENT;
Field | Description |
item_id |
Primary key, auto-increment. |
item_name |
Name of the item. |
item_desc |
Item description. |
bid_end |
Date and time, when the bid ends. Leave this blank if you want to manually close. I.E. Set this to “now” to immediately close the auctioning. |
bid_min |
Minimum bid increment… Or you will get irritating $0.01 increments. |
First, we are going to need a table to hold the items that are being auctioned off. Of course, feel free to add more fields as required – The starting amount, a “buy now” price, etc…
1B) AUCTION BIDS
-- (B) AUCTION BIDS
CREATE TABLE `auction_bids` (
`item_id` bigint(20) NOT NULL,
`user_id` bigint(20) NOT NULL,
`bid_amount` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `auction_bids`
ADD PRIMARY KEY (`item_id`,`user_id`),
ADD KEY `amount` (`bid_amount`);
Field | Description |
item_id |
Partial primary key. |
user_id |
Partial primary key, and foreign key to the users’ table. |
bid_amount |
The amount that the user bid. |
Now, this table should be self-explanatory. But take note that it does not hold the bidding history, only the latest bid by the user. If you want to store the history, you will need to create your own auction_bids_history
table to store every bid – That is pretty much a clone of this table, with an extra date field.
1C) TEST ITEM
-- (C) DUMMY TEST ITEM
INSERT INTO `auction_items`
(`item_name`, `item_img`, `item_desc`, `bid_end`, `bid_min`)
VALUES
('A Box', 'box.png', 'A very high quality brown box, half eaten apple logo available upon request.', NULL, '1.5');
Finally, a dummy test item… Remove this if you don’t need it.
STEP 2) PHP BIDDING LIBRARY
<?php
class Bid {
// (A) CONSTRUCTOR - CONNECT TO DATABASE
private $pdo = null;
private $stmt = null;
public $error = "";
function __construct () {
$this->pdo = new PDO(
"mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=".DB_CHARSET,
DB_USER, DB_PASSWORD, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
}
// (B) DESTRUCTOR - CLOSE DATABASE CONNECTION
function __destruct () {
if ($this->stmt!==null) { $this->stmt = null; }
if ($this->pdo!==null) { $this->pdo = null; }
}
// (C) EXECUTE SQL QUERY
function query ($sql, $data=null) : void {
$this->stmt = $this->pdo->prepare($sql);
$this->stmt->execute($data);
}
// (D) GET ITEM
function getItem ($id) {
// (D1) GET ITEM
$this->query("SELECT * FROM `auction_items` WHERE `item_id`=?", [$id]);
$item = $this->stmt->fetch();
if (!is_array($item)) { return null; }
// (D2) LAST HIGHEST BID + MINIMUM BID AMOUNT
$this->query("SELECT MAX(`bid_amount`) FROM `auction_bids` WHERE `item_id`=?", [$id]);
$item["highest"] = $this->stmt->fetchColumn();
if (!is_numeric($item["highest"])) { $item["highest"] = 0; }
$item["min"] = $item["highest"] + $item["bid_min"];
// (D3) RETURN RESULT
return $item;
}
// (E) UPDATE BID AMOUNT
function setBid ($iid, $uid, $amount) {
// (E1) CHECK IF ITEM EXIST
$item = $this->getItem($iid);
if ($item===null) {
$this->error = "Invalid Item";
return false;
}
// (E2) CHECK IF BIDDING ENDED
if (isset($item["bid_end"]) && strtotime("now") >= strtotime($item["bid_end"])) {
$this->error = "Bidding has ended";
return false;
}
// (E3) CHECK MINIMUM BID AMOUNT
if ($amount < $item["min"]) {
$this->error = "Please bid at least " . $item["min"];
return false;
}
// (E4) UPDATE HIGHEST BID
$this->query(
"REPLACE INTO `auction_bids` (`item_id`, `user_id`, `bid_amount`) VALUES (?,?,?)",
[$iid, $uid, $amount]
);
return true;
}
}
// (F) DATABASE SETTINGS - CHANGE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8mb4");
define("DB_USER", "root");
define("DB_PASSWORD", "");
// (G) NEW TO-DO OBJECT
$_BID = new Bid();
Yikes. This looks confusing at first, but keep calm and look carefully:
- (A, B, G) The constructor will automatically connect to the database when
$_BID = new Bid()
is created, the destructor closes the database connection. - (C)
query()
is a helper function to run an SQL query. - (D & E) There are only 2 library functions!
getItem()
Get the specified item, the details, highest bid, and minimum bid price.setBid()
Save the bid price for the specified item and user.
- (F) Remember to change the database settings to your own.
STEP 3) BID PAGE
<?php
// (A) LOAD LIBRARY
require "2-bid-lib.php";
$iid = 1; // fixed item id for this demo
$uid = 999; // fixed user id for this demo
// (B) UPDATE BID AMOUNT
if (isset($_POST["bid"])) {
$ok = $_BID->setBid($iid, $uid, $_POST["bid"]);
echo "<div class='note'>". ($ok ? "Bid saved" : $_BID->error) ."</div>";
}
// (C) GET ITEM & DISPLAY
$item = $_BID->getItem($iid); ?>
<form method="post" class="bidWrap">
<!-- (C1) ITEM DETAILS -->
<img class="bidImg" src="<?=$item["item_img"]?>">
<div class="bidDetails">
<div class="bidName"><?=$item["item_name"]?></div>
<div class="bidHigh">Highest Bid $<?=sprintf("%0.2f", $item["highest"])?></div>
<div class="bidDesc"><?=$item["item_desc"]?></div>
</div>
<!-- (C2) BID -->
<div class="bidAmt">
<input type="number" name="bid" min="<?=$item["min"]?>" step="<?=$item["bid_min"]?>" value="<?=$item["min"]?>">
<input type="submit" value="BID!">
</div>
</form>
Finally, a page to show the item and open it for bidding.
- Load the library. Take note that the item ID and user ID are fixed for this demo.
- When the bidding form is submitted, we update the bid amount set by the user.
- Get the item and show a “nice HTML bidding form”.
EXTRAS
That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.
FUTURE DEVELOPMENT
Yep, that’s all to the raw mechanics. But as you can see, there are plenty of blanks to fill in:
- The bidding page is fixed, you will want to create your own “dynamic page” by using
$_GET["id"]
,$_POST["id"]
, or even a pretty URL system. - User registration and login system, if you do not already have one.
- Open the bidding page to registered users only.
- Admin panel and functions – Add item, update item, delete item, etc…
- So what happens when the bid ends? Get the user to do an online payment before releasing the item? Send an email to the user that they got the job/contract? Manually schedule a meeting between the seller and bidder?
LINKS & REFERENCES
- User Registration With Email Verification – Code Boxx
- User Login System With PHP MySQL – Code Boxx
- Admin Panel – Code Boxx
THE END
Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!