Lesson 63: Automatically Create Transactions When an Auction Ends Using WordPress Action Hooks

Overview

In the previous lesson, we built the Transaction Manager and created the wp_flipnzee_transactions table. However, transactions are still created manually. The next logical step is to connect the Auction Manager with the Transaction Manager.

Rather than calling the Transaction Manager directly from the Auction Manager, we’ll use one of WordPress’ most powerful features—Action Hooks. This creates a loosely coupled, event-driven architecture where different components communicate through events instead of depending on each other directly.

By the end of this lesson, whenever an auction winner is determined, the plugin will automatically create a pending transaction without modifying the core auction logic.


What You Will Learn

In this lesson you will learn how to:

  • Understand event-driven programming in WordPress.
  • Create a custom WordPress action hook.
  • Pass auction data through an action hook.
  • Listen for custom actions.
  • Automatically create transactions after an auction closes.
  • Reduce coupling between plugin components.
  • Build an extensible architecture for future escrow integrations.

Why This Improvement Matters

Suppose the Auction Manager directly inserts a transaction into the database.

Today that may seem fine.

Tomorrow you may also want to:

  • Send buyer emails.
  • Send seller emails.
  • Start escrow.
  • Notify administrators.
  • Trigger webhooks.
  • Generate invoices.
  • Award badges.
  • Push data to an external CRM.

If every feature is added inside the Auction Manager, the class quickly becomes difficult to maintain.

Using WordPress hooks solves this problem elegantly.

Instead of saying:

“Create a transaction.”

the Auction Manager simply says:

“An auction has ended.”

Any other class can decide whether it wants to respond.


Architecture Before Lesson 63

Auction Manager
      │
      ▼
Determine Winner

Architecture After Lesson 63

Auction Manager
      │
      ▼
do_action()

      │
      ▼

Transaction Manager

      │
      ▼

Create Transaction

Later we can attach even more listeners:

Auction Manager

      │

do_action()

      │
      ├────────► Transaction Manager
      ├────────► Email Manager
      ├────────► Escrow Manager
      ├────────► Notification Manager
      └────────► REST API

This is exactly how many mature WordPress plugins are designed.


What Will Be Implemented

During this lesson we will:

Step 1

Fire a custom action when a winner is determined.


Step 2

Create a listener inside the Transaction Manager.


Step 3

Automatically insert a new transaction.


Step 4

Log transaction creation in the Activity Log.


Step 5

Test the complete workflow.


Expected Result

Before Lesson 63:

Auction Ends

↓

Winner Selected

↓

Nothing Else Happens

After Lesson 63:

Auction Ends

↓

Winner Selected

↓

WordPress Action Fired

↓

Transaction Created

↓

Activity Logged

Files That Will Be Modified

  • includes/class-auction-manager.php
  • includes/class-transaction-manager.php
  • includes/class-activity-log.php

No database changes are required.


Skills You’ll Practice

  • WordPress Action Hooks
  • Custom Events
  • Loose Coupling
  • Event-Driven Programming
  • Clean Plugin Architecture
  • Object-Oriented WordPress Development

Difficulty Level

Intermediate

This lesson introduces one of the most important architectural concepts in WordPress development. Understanding custom action hooks will help you build plugins that are easier to extend, maintain, and integrate with future features such as escrow services, payment gateways, and notification systems.


Final Thoughts

Lesson 63 represents a significant shift in the design of the Flipnzee Auctions plugin. Instead of tightly connecting the Auction Manager with every future component, we will use WordPress’ hook system to broadcast auction events and allow independent classes to respond as needed.

This event-driven approach provides a solid foundation for the remaining roadmap, including escrow integration, payment workflows, buyer and seller notifications, and third-party integrations, while keeping the codebase clean and modular.

Implementing Lesson 62: Building the Transaction Manager Foundation in Flipnzee Auctions

As the Flipnzee Auctions plugin continues to evolve into a complete online auction marketplace, it becomes increasingly important to organize the code into well-defined components. After completing automatic winner determination in the previous lesson, the next step was to introduce a dedicated Transaction Manager.

Instead of embedding transaction logic directly inside the Auction Manager, this lesson focuses on building the architectural foundation that will eventually support escrow integration, payment processing, ownership transfer, and transaction history.

In this implementation, no visible changes are introduced to the plugin interface. However, significant backend improvements prepare the plugin for future marketplace features.


Why a Transaction Manager?

When an auction ends successfully, several business processes may follow:

  • Creating an escrow transaction
  • Recording payment information
  • Sending buyer and seller notifications
  • Tracking ownership transfer
  • Marking the transaction as completed

Rather than placing all of these responsibilities inside the Auction Manager, it is better to create a dedicated class responsible only for transactions.

This follows the Single Responsibility Principle (SRP) and makes the plugin easier to maintain and extend.


Step 1: Create the Transactions Database Table

The first task was extending the database installer to create a new table.

File modified:

includes/class-database.php

A new table was added:

wp_flipnzee_transactions

using dbDelta().

/*
 * Create transactions table.
 */
$transaction_table = $wpdb->prefix . 'flipnzee_transactions';

$sql = "CREATE TABLE {$transaction_table} (

	id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,

	auction_id BIGINT UNSIGNED NOT NULL,

	listing_id BIGINT UNSIGNED NOT NULL,

	seller_id BIGINT UNSIGNED NOT NULL,

	buyer_id BIGINT UNSIGNED NOT NULL,

	winning_bid DECIMAL(12,2) NOT NULL,

	status VARCHAR(30) DEFAULT 'pending',

	created_at DATETIME DEFAULT CURRENT_TIMESTAMP,

	updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,

	PRIMARY KEY (id),

	KEY auction_id (auction_id),

	KEY buyer_id (buyer_id),

	KEY seller_id (seller_id),

	KEY status (status)

) {$charset_collate};";

dbDelta( $sql );

After reactivating the plugin, the new database table appeared successfully in phpMyAdmin.


Step 2: Create the Transaction Manager

A brand-new class was introduced.

New file:

includes/class-transaction-manager.php

Initial class structure:

<?php
/**
 * Transaction Manager.
 *
 * @package Flipnzee_Auctions
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Flipnzee_Transaction_Manager {

}

This dedicated class will manage all transaction-related functionality in future lessons.


Step 3: Load the New Class

The main plugin loader was updated to include the new class.

File modified:

flipnzee-auctions.php

Code added:

require_once FLIPNZEE_AUCTION_PATH .
	'includes/class-transaction-manager.php';

This ensures the Transaction Manager is available throughout the plugin.


Step 4: Create Transactions Programmatically

The first functional method was added.

/**
 * Create a transaction.
 *
 * @param array $data Transaction data.
 * @return int|false
 */
public static function create_transaction( $data ) {

	global $wpdb;

	$table = $wpdb->prefix . 'flipnzee_transactions';

	$result = $wpdb->insert(
		$table,
		array(
			'auction_id'  => $data['auction_id'],
			'listing_id'  => $data['listing_id'],
			'seller_id'   => $data['seller_id'],
			'buyer_id'    => $data['buyer_id'],
			'winning_bid' => $data['winning_bid'],
			'status'      => 'pending',
		),
		array(
			'%d',
			'%d',
			'%d',
			'%d',
			'%f',
			'%s',
		)
	);

	if ( false === $result ) {
		return false;
	}

	return $wpdb->insert_id;
}

Although not yet connected to auction completion, this method provides the core functionality for creating marketplace transactions.


Step 5: Retrieve a Transaction

A second method was implemented for retrieving transaction details.

/**
 * Get a transaction.
 *
 * @param int $transaction_id Transaction ID.
 * @return object|null
 */
public static function get_transaction( $transaction_id ) {

	global $wpdb;

	$table = $wpdb->prefix . 'flipnzee_transactions';

	return $wpdb->get_row(
		$wpdb->prepare(
			"SELECT * FROM {$table} WHERE id = %d",
			$transaction_id
		)
	);
}

Keeping database queries inside the Transaction Manager avoids repeating SQL throughout the plugin.


Step 6: Update Transaction Status

Finally, a method was added for updating transaction status.

/**
 * Update transaction status.
 *
 * @param int    $transaction_id Transaction ID.
 * @param string $status         New status.
 * @return bool
 */
public static function update_status(
	$transaction_id,
	$status
) {

	global $wpdb;

	$table = $wpdb->prefix . 'flipnzee_transactions';

	$result = $wpdb->update(
		$table,
		array(
			'status' => sanitize_text_field( $status ),
		),
		array(
			'id' => absint( $transaction_id ),
		),
		array(
			'%s',
		),
		array(
			'%d',
		)
	);

	return false !== $result;
}

This method will later allow the plugin to move transactions through stages such as:

  • Pending
  • Escrow Started
  • Payment Received
  • Ownership Transferred
  • Completed
  • Cancelled

Testing the Implementation

After completing the changes:

  • The plugin activated successfully.
  • No PHP syntax errors were reported.
  • The wp_flipnzee_transactions table was successfully created.
  • The new Transaction Manager loaded correctly.
  • Existing auction functionality remained unaffected.

This confirmed that the new architecture had been integrated without breaking existing features.

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


Lessons Learned

This lesson demonstrates an important software engineering principle:

Build the architecture before building the features.

Although users cannot yet create or view transactions, introducing a dedicated Transaction Manager now will make future development much cleaner.

Future features such as escrow integration, payment gateways, notifications, and transaction history can all be implemented within this class without increasing the complexity of the Auction Manager.


Final Thoughts

Lesson 62 marks an important milestone in the Flipnzee Auctions project. Rather than focusing on user-facing functionality, this lesson strengthens the plugin’s internal architecture by introducing a dedicated Transaction Manager and transaction database table.

As the plugin grows into a full-featured auction marketplace, this modular design will make future enhancements significantly easier to implement, maintain, and extend.

In the next lesson, we will connect the Auction Manager and the Transaction Manager using WordPress action hooks so that a transaction is created automatically whenever an auction winner is determined. This event-driven approach will further improve the plugin’s flexibility and maintainability.

Lesson 62: Building the Transaction Manager Foundation for Flipnzee Auctions

With automatic winner determination now complete, the Flipnzee Auctions plugin has reached an important milestone. Every completed auction now has a confirmed winner and a final bid amount.

The next logical step is not to integrate directly with an escrow service. Instead, we first need to build a solid transaction management layer that will act as the bridge between completed auctions and future payment or escrow workflows.

In this lesson, we will create the Transaction Manager Foundation, providing the architecture that will support escrow providers, payment gateways, notifications, and transaction tracking in future lessons.


Why Not Integrate Escrow Immediately?

When developing marketplace software, it is tempting to connect directly to an escrow provider as soon as a winner has been selected.

However, this creates tight coupling between auction logic and payment processing.

Instead, professional marketplace platforms introduce a separate transaction layer.

The workflow becomes:

Auction
      ↓
Winner Determined
      ↓
Transaction Created
      ↓
Escrow
      ↓
Ownership Transfer
      ↓
Transaction Completed

This separation makes the system easier to maintain, extend, and test.


Why Introduce a Transaction Manager?

The Auction Manager should remain responsible only for auction-related operations such as:

  • creating auctions,
  • activating auctions,
  • closing auctions,
  • determining winners.

It should not become responsible for:

  • escrow,
  • payment processing,
  • notifications,
  • transaction history.

Those responsibilities belong to a dedicated Transaction Manager.

Following the Single Responsibility Principle (SRP) keeps each class focused on one area of responsibility.


What We Will Build

During this lesson we will create a brand-new class:

includes/class-transaction-manager.php

This class will become responsible for managing every transaction that occurs after an auction has completed.

Initially, it will provide methods such as:

  • Create Transaction
  • Retrieve Transaction
  • Update Transaction Status

Additional capabilities will be added in later lessons.


Creating a Transactions Table

To support transaction management, a new database table will be introduced:

wp_flipnzee_transactions

Each completed auction will eventually create a corresponding transaction record.

The table is designed to store information such as:

  • Transaction ID
  • Auction ID
  • Listing ID
  • Seller ID
  • Buyer ID
  • Winning Bid
  • Transaction Status
  • Creation Date
  • Last Updated Date

Having a dedicated table keeps transaction information separate from auction data while allowing both systems to remain connected.


Benefits of a Separate Transaction Layer

This design offers several important advantages.

Clean Architecture

Each manager class performs one job.

Auction Manager manages auctions.

Bid Manager manages bids.

Transaction Manager manages transactions.

Future managers can handle:

  • Escrow
  • Notifications
  • Payments
  • Emails

without modifying the auction engine.


Easier Escrow Integration

Whether Flipnzee eventually integrates with:

  • Escrow.com,
  • another escrow provider,
  • manual escrow,
  • or an in-house payment system,

all of them can simply interact with the Transaction Manager rather than modifying auction logic.


Improved Maintainability

As new features are added, developers will know exactly where transaction-related code belongs.

Instead of one extremely large manager class, the plugin grows through focused, modular components.


Preparing for Future Lessons

This architectural foundation prepares the plugin for several major features.

Upcoming lessons will build on the Transaction Manager by adding:

  • Automatic transaction creation
  • Winner notifications
  • Seller notifications
  • Transaction status updates
  • Escrow integration
  • Payment tracking
  • Ownership transfer workflow

Each feature will plug into the Transaction Manager without requiring major changes to the existing auction system.


What You’ll Learn

In this lesson, you will learn how to:

  • Design a scalable WordPress plugin architecture.
  • Apply the Single Responsibility Principle.
  • Create a dedicated database table for transactions.
  • Build a reusable Transaction Manager.
  • Prepare a plugin for future integrations.
  • Separate business logic into modular components.

Why the Roadmap Was Revised

Originally, the plan was to create transactions directly inside the Auction Manager.

During implementation, it became clear that this would gradually turn the Auction Manager into a very large class responsible for multiple unrelated tasks.

The architecture was therefore improved before the feature was completed.

Instead of tightly coupling auctions with transactions, the project now introduces a dedicated Transaction Manager that communicates with the rest of the plugin through well-defined methods and WordPress actions.

This approach closely follows the modular architecture used throughout WordPress itself.


Final Thoughts

As software projects grow, architecture becomes just as important as functionality.

Introducing a Transaction Manager may not produce an immediately visible feature for users, but it establishes a clean, scalable foundation that will support every post-auction process in the future.

By investing in a well-structured architecture now, the Flipnzee Auctions plugin is better prepared for secure escrow integration, transaction tracking, and the complete marketplace workflow that will power Flipnzee.com.


Next Lesson

In Lesson 63, we will connect the Auction Manager and the Transaction Manager using WordPress action hooks, allowing transactions to be created automatically whenever a winner is determined—without tightly coupling the two classes.

Lesson 61 Implementation: Automatically Determine the Winning Bidder When an Auction Ends

One of the most important milestones in the Flipnzee Auctions project has now been completed. In this lesson, the plugin was enhanced to automatically determine the winning bidder as soon as an auction expires.

Previously, the plugin was already capable of automatically closing expired auctions. However, after the auction was closed, no winner was selected automatically. An administrator would have needed to determine the highest bidder manually.

This lesson bridges that gap and moves the project much closer to becoming a fully functional online auction marketplace.


Objective

The goal of this lesson was to:

  • Detect the highest valid bid after an auction closes.
  • Save the winning bidder in the auction record.
  • Update the final bid amount.
  • Record the event in the Flipnzee Activity Log.
  • Lay the foundation for future escrow integration.

The Problem

The plugin already contained logic that automatically changed an auction’s status from Active to Closed after the auction end time.

However, closing an auction alone is not sufficient.

A complete auction workflow should also:

  • Find the highest bidder.
  • Declare the winner.
  • Store the winner permanently.
  • Prepare the transaction for the next stage.

Without this step, the marketplace cannot proceed to payment or escrow.


Implementation Overview

The implementation consisted of three major improvements.

1. Creating a Winner Selection Method

A new method named determine_winner() was added to the Bid Manager.

Its responsibility is to:

  • Retrieve all bids for an auction.
  • Sort bids by highest amount.
  • Use the earliest bid as the tie-breaker.
  • Save the winning bidder.
  • Update the final bid.
  • Record the event in the activity log.

This centralizes the winner selection logic so it can be reused in future features.


2. Updating the Auction Closing Process

The auction closing routine was modified to perform two operations:

  1. Automatically close expired auctions.
  2. Immediately determine the winner for every auction that was closed.

Before updating auction statuses, the IDs of all expired auctions are collected.

Once the status update completes successfully, the plugin loops through those auction IDs and calls the new winner selection method.

This keeps the code clean while ensuring every expired auction receives a winner automatically.


3. Recording the Winner

After selecting the winning bid, the plugin stores:

  • Winning User ID
  • Final Bid Amount

inside the auction record.

It also records a new activity log entry similar to:

winner_determined
Auction: 31
User: 2
Winning bid: 55555609.00

This creates an audit trail that administrators can review at any time.


Testing the Feature

After uploading the updated plugin:

  • The plugin activated successfully.
  • An auction automatically changed to Closed after expiration.
  • The highest bidder was identified correctly.
  • The winner was saved.
  • A new winner_determined entry appeared in the Activity Log.

This confirmed that the entire workflow executed successfully.


Challenges Faced

During development, one major issue occurred.

The plugin failed to activate because of a PHP parse error caused by an incorrectly placed closing brace inside the admin class.

Using:

php -l admin/class-admin.php

made it possible to quickly identify the syntax issue.

After correcting the misplaced brace and re-uploading the plugin, activation succeeded.

This served as another reminder of the importance of validating PHP files before deployment.


Files Modified

The following files were updated during this lesson:

  • includes/class-bid-manager.php
  • includes/class-auction-manager.php

No database schema changes were required because the necessary fields already existed.


What Was Achieved

By the end of this lesson, the Flipnzee Auctions plugin can now:

  • Automatically close expired auctions.
  • Identify the highest bidder.
  • Resolve ties using the earliest bid.
  • Save the winner in the auction record.
  • Update the final bid amount.
  • Record the event in the Activity Log.

These enhancements significantly improve the automation of the auction lifecycle.


Lessons Learned

Several important development practices were reinforced:

  • Separate business logic into reusable methods.
  • Keep auction closing and winner determination as distinct responsibilities.
  • Always validate PHP files using php -l before deployment.
  • Activity logging is invaluable when testing automated workflows.

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


Looking Ahead

With automatic winner determination now complete, the next stage of development will focus on transforming a completed auction into a real transaction.

Upcoming lessons will introduce:

  • Buyer and seller notifications.
  • Transaction records.
  • Escrow workflow preparation.
  • Payment integration.
  • Marketplace completion.

The project has now moved beyond simply displaying auctions. It is steadily evolving into a complete auction marketplace capable of supporting secure, end-to-end online transactions.

Lesson 61: Automatically Determine the Winning Bidder When an Auction Ends

One of the most important milestones in the Flipnzee Auctions plugin is moving from simply accepting bids to automatically determining the winner once an auction expires.

Until now, the plugin has allowed visitors to place bids, displayed the highest bidder, tracked activity, and automatically closed expired auctions. However, once an auction ended, there was no definitive step that officially declared a winner.

In this lesson, we will build the logic that identifies the highest valid bidder and records them as the auction winner.


Why This Feature Matters

An auction is only complete when a winner has been determined.

Without this feature:

  • administrators must manually inspect bid history,
  • mistakes can occur,
  • notifications cannot be automated,
  • escrow cannot begin,
  • ownership transfer cannot proceed.

Automatically determining the winner removes manual work while increasing trust in the auction platform.


What We Will Build

By the end of this lesson, the plugin will:

  • detect when an auction closes,
  • retrieve all valid bids,
  • determine the highest bidder,
  • resolve ties fairly,
  • save the winning bidder,
  • save the winning bid amount,
  • prepare the auction for the escrow workflow.

Planned Database Changes

The auction record will be enhanced with dedicated winner information.

Examples include:

  • Winner User ID
  • Winning Bid
  • Winning Time
  • Auction Result Status

This allows the plugin to remember the winning bidder even after additional administrative actions are taken.


Winner Selection Rules

The plugin should follow a clear and transparent process.

For example:

  1. Auction expires.
  2. Retrieve all bids.
  3. Ignore invalid bids.
  4. Sort by highest bid.
  5. If multiple bids have the same amount, choose the earliest one.
  6. Store the winner.
  7. Mark the auction as completed.

This ensures every auction follows the same rules.


Preparing for Escrow Integration

Determining the winner is the foundation for the next major milestone.

Once a winner exists, the plugin can automatically:

  • notify the buyer,
  • notify the seller,
  • initiate an escrow transaction,
  • display payment instructions,
  • begin ownership transfer.

Without a confirmed winner, none of these workflows can begin.


Administrator Benefits

Instead of manually checking bid history, administrators will immediately know:

  • who won,
  • the winning amount,
  • when the winning bid was placed,
  • whether the auction completed successfully.

This reduces administration time and minimizes disputes.


Future Enhancements

The winner information introduced in this lesson will later support features such as:

  • Winner email notifications
  • Seller notifications
  • Escrow integration
  • Transaction tracking
  • Buyer dashboard
  • Seller dashboard
  • Completed auction history
  • Marketplace reputation system

What You’ll Learn

In this lesson, you will learn how to:

  • query auction bids efficiently,
  • determine the highest valid bid,
  • handle tie-breaking rules,
  • update auction records,
  • prepare auctions for post-auction workflows,
  • design software that supports future business processes.

Final Thoughts

Automatically determining the winning bidder marks the transition from a bidding system to a complete auction platform. It establishes a trusted and repeatable process for ending auctions fairly and creates the foundation for escrow, notifications, and secure ownership transfer.

In Lesson 62, we will build the Auction Completion Workflow, automatically transitioning completed auctions into the next stage of the transaction lifecycle.

Lesson 60: Parsing Activity Logs into a Professional Admin Table in the Flipnzee Auctions Plugin

As the Flipnzee Auctions plugin continued to evolve, the Activity Log introduced in previous lessons became increasingly useful for tracking important auction events. However, displaying each log entry as a single line made it difficult to scan and understand.

In this lesson, the plugin was enhanced to parse each log entry and display it inside a structured WordPress admin table. This small improvement greatly increases readability and lays the groundwork for advanced features like searching, filtering, exporting, and pagination.


Why Improve the Activity Log?

A plain text log might work for developers, but administrators need information that is easy to understand at a glance.

Instead of displaying this:

[2026-07-05 19:19:14] Event: auction_auto_closed | Auction: 0 | User: 0 | Details: 1 auction(s) automatically closed.

the Activity Log now presents the information in separate columns.

Date & TimeEventAuctionUserDetails
2026-07-05 19:19:14auction_auto_closed001 auction(s) automatically closed.

This makes the history of auction activity much easier to browse.


What Was Implemented

During this lesson, the Activity Log renderer was upgraded to:

  • Read each log entry from the log file
  • Parse the stored text using a regular expression
  • Extract individual values
  • Display the information inside a structured HTML table
  • Continue displaying unknown log formats safely using a fallback

Understanding the Log Format

Every activity recorded by the plugin follows a consistent structure.

Example:

[2026-07-05 19:19:14] Event: auction_auto_closed | Auction: 0 | User: 0 | Details: 1 auction(s) automatically closed.

The parser separates this into five individual fields:

  • Date & Time
  • Event
  • Auction ID
  • User ID
  • Details

Because every log entry follows the same format, PHP can reliably extract the values before displaying them.


Using Regular Expressions

The parser uses PHP’s preg_match() function to identify each section of the log.

Rather than treating the entire line as plain text, it captures the different values individually.

This allows each value to be displayed inside its own table cell.


Creating the Admin Table

Instead of printing one long string, the renderer now creates a table containing:

  • Date & Time
  • Event
  • Auction
  • User
  • Details

Each log entry becomes a separate row.

The result is much cleaner and far easier to read.


Fallback for Unexpected Entries

Not every log file remains perfectly formatted forever.

To prevent errors, the renderer checks whether the regular expression successfully matches the expected format.

If it does, the values are displayed in separate columns.

If not, the original log line is still displayed safely inside a single table row.

This ensures older or unexpected entries never disappear.


Testing the Feature

After updating the plugin:

  1. Upload the latest plugin ZIP.
  2. Activate the plugin.
  3. Open:

Flipnzee Auctions → Activity Log

If log entries already exist, they should automatically appear as structured table rows.


Final Result

The Activity Log is now significantly more useful for administrators.

Instead of reading long text strings, administrators can quickly identify:

  • when something happened,
  • what event occurred,
  • which auction was involved,
  • which user performed the action,
  • and additional details.

This makes troubleshooting and auditing much easier.


What I Learned

This lesson demonstrated how small user interface improvements can dramatically improve usability.

Key concepts covered included:

  • Reading log files
  • Parsing structured text
  • Using PHP regular expressions
  • Displaying dynamic data inside HTML tables
  • Building fallback logic for unexpected input
  • Improving the WordPress admin experience

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


Looking Ahead

With structured activity logs now working, the next logical improvements include:

  • Search within logs
  • Filter events by type
  • Download logs as CSV
  • Pagination for large log files
  • Clear log button
  • Colour-coded event badges
  • Date range filtering

These enhancements will transform the Activity Log into a powerful administration and debugging tool for the Flipnzee Auctions plugin.


Lesson 60 Complete! The Flipnzee Auctions plugin now features a professional, structured Activity Log that presents auction events in an organized table, making plugin administration cleaner, faster, and more user-friendly.

Lesson 60: Display Activity Logs in a Professional WordPress Admin Table

Overview

In Lesson 59, the Flipnzee Auctions plugin gained a dedicated Activity Log page that displays the contents of the log file. While functional, presenting raw log entries inside a text area isn’t ideal for administrators managing a busy auction marketplace.

In this lesson, we’ll redesign the Activity Log page by displaying each log entry in a clean WordPress-style table with separate columns for the timestamp, event, auction ID, user ID, and details.


What You Will Learn

  • Read and parse log entries from a text file.
  • Convert plain text into structured PHP arrays.
  • Build a professional HTML table using WordPress admin styling.
  • Improve readability for administrators.
  • Lay the foundation for future features like search, filtering, pagination, CSV export, and log deletion.

Current Output

Recent auction activity recorded by the plugin.

[2026-07-05 19:19:14] Event: auction_auto_closed | Auction: 0 | User: 0 | Details: 1 auction(s) automatically closed.

New Output

Date & TimeEventAuctionUserDetails
2026-07-05 19:19:14auction_auto_closed001 auction automatically closed

Why This Improvement Matters

Displaying logs as structured data makes them much easier to:

  • scan quickly
  • troubleshoot auction problems
  • identify system events
  • prepare for future search and filtering

It also gives the plugin a much more polished and professional appearance.


Implementation Roadmap

Step 1

Read the activity log file.

Step 2

Split the file into individual log entries.

Step 3

Extract:

  • timestamp
  • event
  • auction ID
  • user ID
  • details

using PHP string functions or regular expressions.

Step 4

Store each entry in an array.

Step 5

Generate a WordPress admin table.

Step 6

Handle empty or missing log files gracefully.

Step 7

Test with multiple log entries.


Skills Covered

  • File parsing
  • String manipulation
  • Arrays
  • Regular expressions
  • WordPress admin UI
  • HTML tables
  • Defensive programming

Expected Outcome

By the end of this lesson, the Flipnzee Auctions plugin will feature a professional Activity Log dashboard where every event is neatly organized into columns, making monitoring and troubleshooting significantly easier.


I think this is a strong progression from Lesson 59 because it builds directly on the feature you just implemented while introducing practical PHP skills such as file parsing and structured data handling. It also creates a solid foundation for future lessons like searching logs (Lesson 61), clearing logs (Lesson 62), or exporting logs to CSV (Lesson 63).

Lesson 59: Building an Activity Log Viewer in the WordPress Admin Dashboard

During the previous lesson, the Flipnzee Auctions plugin gained the ability to record important events such as automatically closing expired auctions. While the log file was successfully written to the server, administrators still needed to open the file manually through the hosting control panel to view it.

In this lesson, the plugin was enhanced with a dedicated Activity Log page inside the WordPress admin dashboard, allowing administrators to view recent activity directly from WordPress.


What We Wanted to Achieve

Instead of navigating to:

wp-content/uploads/flipnzee-logs/activity.log

using a file manager, the goal was to provide an easy-to-access interface under the plugin’s own admin menu.

The desired workflow became:

Flipnzee Auctions
    ├── Dashboard
    ├── Add Auction
    ├── Activity Log
    ├── All Auctions
    └── Edit Auction

Selecting Activity Log would display the contents of the log file inside the WordPress dashboard.


Step 1 – Create a New Admin Page Class

A new file was created:

admin/class-admin-activity-log.php

This class is responsible for:

  • locating the activity log file
  • reading its contents
  • displaying the information inside the WordPress admin area

Separating this functionality into its own class keeps the plugin modular and easier to maintain.


Step 2 – Register the New Class

The new class file was loaded inside the main plugin file.

A conditional require_once statement was added so the class is only included when the file exists.

This follows the same loading pattern used throughout the plugin.


Step 3 – Add a New Submenu

A new submenu was registered inside the existing Flipnzee Auctions menu.

Administrators can now access the log from:

Flipnzee Auctions
→ Activity Log

No additional permissions were required because the page already uses the existing administrator capability.


Step 4 – Create the Page Callback

Inside the admin class, a new callback method was added.

Its only responsibility is to call the renderer from the Activity Log class.

Keeping the controller small makes future maintenance much easier.


Step 5 – Display the Log File

The Activity Log page checks whether the following file exists:

wp-content/uploads/flipnzee-logs/activity.log

If found, the contents are displayed inside a large read-only text area.

If the file does not yet exist, a friendly message is shown instead.


Step 6 – Test the Feature

An auction was allowed to expire automatically.

The maintenance task successfully recorded:

Event: auction_auto_closed

along with the number of auctions processed.

Opening the Activity Log page immediately displayed the newly written entry.

This confirmed that:

  • the scheduled maintenance worked
  • logging worked
  • the admin page successfully read the log file

A Real Debugging Lesson

During implementation, the plugin initially failed to activate.

The server reported:

PHP Parse error:
unexpected token "public"

The problem turned out to be a missing closing brace (}) inside the register_menu() method.

Because the method never ended, PHP interpreted the next function declaration as being inside another function.

After inserting the missing brace:

}

the plugin activated normally.

This was an excellent reminder that many “fatal plugin errors” are caused by simple structural mistakes.


Verifying Syntax Before Uploading

Before uploading the updated plugin, syntax was checked locally using PHP’s built-in linter:

php -l admin/class-admin.php

The result:

No syntax errors detected

Performing this quick validation can save significant debugging time.


Final Result

The plugin now includes a fully integrated Activity Log viewer inside WordPress.

Administrators no longer need to browse server folders or download log files manually.

Recent auction activity is available directly from the dashboard with a single click.

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


What We Learned

In this lesson we learned how to:

  • create a dedicated WordPress admin page
  • organize admin functionality into separate classes
  • register submenu pages
  • display server-generated log files
  • safely include new PHP classes
  • diagnose plugin activation failures
  • use PHP’s syntax checker before deployment
  • integrate logging with an administrator-friendly interface

Tips

  • Keep logging logic separate from display logic.
  • Always validate PHP syntax before uploading a plugin update.
  • Read server error logs whenever a plugin fails to activate.
  • Organize admin pages into dedicated classes instead of placing all code in one file.
  • Simple logging features become invaluable when troubleshooting production websites.

Outcome: The Flipnzee Auctions plugin now provides a built-in Activity Log page that lets administrators monitor important auction events directly from the WordPress dashboard, making debugging and maintenance much more convenient.

Lesson 59 – Build an Admin Activity Log Viewer for Flipnzee Auctions


Difficulty

Intermediate


What You’ll Learn

In this lesson, you’ll build the first administrative interface for the new logging system.

Instead of opening activity.log via File Manager or FTP, administrators will be able to read recent plugin activity directly from the WordPress dashboard.

By the end of this lesson, your plugin will:

  • Read the activity log file
  • Display recent entries inside wp-admin
  • Handle missing log files gracefully
  • Limit the number of displayed entries
  • Escape output securely
  • Prepare the foundation for future filtering and search

Why This Matters

Professional plugins don’t require developers to inspect server files.

They provide useful diagnostics directly inside WordPress.

This lesson transforms the logging system from a developer-only feature into an administrator-friendly tool.


What We’ll Build

A new admin page similar to:

Flipnzee Auctions
│
├── Dashboard
├── Auctions
├── Activity Log   ← NEW
└── Settings

The page will display something like:

Recent Activity

[2026-07-05 19:19:14]
Auction automatically closed

------------------------------------

[2026-07-05 18:42:03]
Bid placed

------------------------------------

[2026-07-05 17:58:10]
Auction created

Implementation Roadmap

Step 1

Create a new admin page:

Activity Log

Step 2

Locate

wp-content/uploads/
flipnzee-logs/activity.log

Step 3

Read the log safely using WordPress filesystem functions.


Step 4

Display only the most recent entries (for example, last 100 lines).


Step 5

Escape all output using:

esc_html()

Step 6

Show a friendly message if the log file doesn’t exist:

No activity has been recorded yet.

Step 7

Add basic styling for readability.


Best Practices You’ll Learn

  • Reading files safely
  • Preventing XSS with escaped output
  • Building admin pages
  • Working with plugin-generated files
  • Preparing data for future search/filter features

Files We’ll Modify

admin/class-admin.php
admin/class-admin-activity-log.php   (new)
assets/admin.css   (optional)

Skills You’ll Gain

After this lesson, you’ll know how to:

  • Create professional admin tools
  • Display plugin-generated files
  • Build diagnostic pages
  • Improve administrator experience
  • Extend your plugin without touching the frontend

What Comes Next

After completing this lesson, we’ll continue with:

Lesson 60 – Add a “Clear Activity Log” Button with WordPress Nonce Protection

In that lesson, administrators will be able to safely clear the activity log from the dashboard, while learning secure form handling and nonce verification.

This sequence will gradually turn Flipnzee Auctions into a production-quality WordPress plugin with professional monitoring and maintenance features.

Lesson 58 Implementation: Adding a Persistent Activity Logging System to Flipnzee Auctions

In the previous lesson, we introduced WordPress hooks so that other plugins and future Flipnzee components could respond whenever auctions were automatically closed.

In this lesson, we take the next step by building a lightweight activity logging system. Instead of silently processing important events, the plugin now records them in a dedicated log file. This creates an audit trail that helps during debugging, monitoring, and future analytics development.


What We Built

By the end of this lesson, the plugin can:

  • Create a dedicated logging class
  • Automatically create a log directory if it doesn’t exist
  • Create an activity.log file
  • Record important auction events
  • Store timestamps and useful event details
  • Keep logs separate from WordPress debug.log

Example log entry:

[2026-07-05 19:19:14]
Event: auction_auto_closed
Auction: 0
User: 0
Details: 1 auction(s) automatically closed.

Step 1 — Create the Activity Logger

A new file was added:

includes/class-activity-log.php

This class is responsible for:

  • Creating the log directory
  • Creating the log file
  • Formatting log entries
  • Writing entries safely

Instead of scattering error_log() calls throughout the plugin, everything now goes through one reusable class.

Benefits include:

  • Cleaner code
  • Easier maintenance
  • Centralized logging
  • Future extensibility

Step 2 — Load the Logger

The new logger class was loaded inside the main plugin file:

flipnzee-auctions.php

The class is included only if the file exists:

require_once FLIPNZEE_AUCTION_PATH .
    'includes/class-activity-log.php';

This ensures the logger is available everywhere in the plugin.


Step 3 — Record Automatic Auction Closures

Inside:

includes/class-auction-manager.php

The existing method:

update_expired_auctions()

was enhanced.

After expired auctions are closed automatically, the plugin now records a log entry.

Example:

if ( $updated_count > 0 ) {

    Flipnzee_Activity_Log::log(
        'auction_auto_closed',
        0,
        0,
        sprintf(
            '%d auction(s) automatically closed.',
            $updated_count
        )
    );
}

This means activity is only logged when one or more auctions were actually updated.


Step 4 — Store Logs in a Dedicated Folder

Rather than using WordPress’s global debug log, the plugin now creates its own directory:

wp-content/uploads/
    flipnzee-logs/
        activity.log

Keeping logs separate provides several advantages:

  • Easier troubleshooting
  • Cleaner WordPress debug logs
  • Plugin-specific history
  • Better preparation for future analytics features

Step 5 — Test the Logger

To verify everything worked:

  1. Created an auction that would expire shortly.
  2. Waited for the auction to expire.
  3. Allowed the plugin to automatically close the auction.
  4. Opened the log file on the server.

The log contained:

Event: auction_auto_closed
Details: 1 auction(s) automatically closed.

This confirmed that:

  • automatic expiration worked,
  • the logger executed correctly,
  • and the activity file was successfully written.

Final Result

The Flipnzee Auctions plugin now includes its own lightweight activity logging framework.

Important auction events can now be recorded without relying on WordPress debug logs, making troubleshooting significantly easier during development.

More importantly, this logging infrastructure lays the groundwork for future features such as:

  • administrator activity history
  • bidder activity logs
  • seller notifications
  • email event tracking
  • analytics dashboards
  • security auditing
  • webhook monitoring
  • plugin diagnostics

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


Key Takeaways

During this lesson, we:

  • Created a reusable Flipnzee_Activity_Log class.
  • Loaded the logger through the main plugin bootstrap.
  • Logged automatic auction closures.
  • Stored logs in wp-content/uploads/flipnzee-logs/activity.log.
  • Successfully verified that the logger writes real events to disk.

The Flipnzee Auctions plugin now has a solid foundation for tracking important marketplace activity, making future debugging, reporting, and analytics much easier.