Lesson 53 Implementation: Prevent Duplicate Auctions by Enforcing One Auction Per Listing
As the Flipnzee Auctions plugin matured, an important database design issue became apparent. During testing, it was possible to create multiple auction records for the same listing. While acceptable during development, this behaviour could lead to incorrect auction displays, duplicated auction cards, and confusion when retrieving bid history.
In this lesson, we improved the auction creation process by enforcing a simple but important rule:
One listing can have only one auction.
Instead of creating duplicate auction records, the plugin now updates the existing auction whenever the administrator attempts to create another auction for the same listing.
The Problem
Originally, every time an auction was created, a new database record was inserted.
For example:
Listing ID 491
Auction #25
Auction #26
Auction #27
Auction #31
Although only one auction should exist for the listing, several records accumulated during development.
This caused problems such as:
- Multiple auction cards appearing.
- Incorrect auction selected by frontend queries.
- Bid history associated with different auction IDs.
- Difficult database maintenance.
Step 1: Check Whether an Auction Already Exists
Inside:
includes/class-auction-manager.php
Locate:
public static function create_auction()
Immediately after defining the database table, retrieve any existing auction for the current listing.
$existing_auction = $wpdb->get_var(
$wpdb->prepare(
"SELECT id
FROM {$table}
WHERE listing_id = %d
LIMIT 1",
$listing_id
)
);
If an auction already exists, the plugin now knows its auction ID before attempting to insert another record.
Step 2: Update Instead of Insert
Previously, the function always continued directly to:
$wpdb->insert(
Instead, we added:
if ( $existing_auction ) {
self::update_auction(
$existing_auction,
$listing_id,
$start_price,
$reserve_price,
$buy_now_price,
'active',
$auction_start,
$auction_end
);
return $existing_auction;
}
This means:
- Existing auction found → update it.
- No auction found → create a brand-new auction.
Step 3: Keep Existing Insert Logic
If no auction exists, the original insert code continues to run unchanged.
$result = $wpdb->insert(
$table,
array(
'listing_id' => $listing_id,
'start_price' => $start_price,
'reserve_price' => $reserve_price,
'buy_now_price' => $buy_now_price,
'status' => 'active',
'auction_start' => $auction_start,
'auction_end' => $auction_end,
),
array(
'%d',
'%f',
'%f',
'%f',
'%s',
'%s',
'%s',
)
);
No further changes were required.
Why Return the Existing Auction ID?
The create_auction() method was originally designed to return the auction ID.
Returning:
true
would change the method’s behaviour and could break other parts of the plugin.
Instead, after successfully updating an existing auction, we return:
return $existing_auction;
This preserves the original method contract and keeps the plugin consistent.
Testing
To verify the implementation:
- Edit an existing listing.
- Create (or recreate) its auction.
- Save the auction.
- Check the Auctions table.
Expected behaviour:
- No new auction record is created.
- The existing auction is updated.
- The auction ID remains unchanged.
- Auction dates and prices are refreshed successfully.
Testing confirmed that the plugin now updates the existing auction instead of creating duplicates.
Development Observation
While testing, previously created development records remained in the database.
For example:
Listing ID 491
Auction #25 (closed)
Auction #26 (closed)
Auction #27 (closed)
Auction #31 (active)
These historical records were created before this lesson was implemented.
Because Lesson 53 prevents future duplicate creation, a clean database (or removal of old development records) ensures that each listing has only one associated auction going forward.
What We Learned
This lesson demonstrated an important database design principle:
Prevent duplicate data instead of fixing it later.
By checking for an existing auction before inserting a new one, the plugin now enforces a one-to-one relationship between listings and auctions. This keeps the database cleaner, simplifies frontend queries, and ensures that auction history and bid data remain associated with the correct auction record.
Download Source Code
Download the starting version of the plugin before the lesson:
⬇ Download Plugin (After Lesson 52) (5 downloads )Download the completed version after this lesson:
⬇ Download Plugin (After Lesson 53) (3 downloads )Final Thoughts
Although the implementation itself was straightforward, it significantly improved the overall architecture of the Flipnzee Auctions plugin. Preventing duplicate auctions not only reduces database clutter but also lays a stronger foundation for future features such as auction archives, winner announcements, relisting, and auction history. From this point onward, each listing is managed through a single auction record, making the system more reliable and easier to maintain.
