Implementing automated compliance reporting for custom event ticket registers ledgers using mpdf engine
Leveraging mPDF for Automated Compliance Reporting of Custom Event Ticket Registers
Enterprise environments often require robust audit trails for critical operations, especially those involving financial transactions or access control. Custom event ticket registers, acting as immutable ledgers for ticket creation, modification, and closure, are prime candidates for automated compliance reporting. This document details a practical implementation strategy using the mPDF library in PHP to generate auditable, PDF-formatted reports directly from such a register.
Database Schema for Event Ticket Register
A foundational element is a well-structured database table to store event ticket data. For compliance purposes, immutability and detailed logging are paramount. Consider a schema like the following:
CREATE TABLE `event_tickets` (
`id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`ticket_uuid` BINARY(16) NOT NULL UNIQUE COMMENT 'Globally unique identifier for the ticket',
`event_type` VARCHAR(100) NOT NULL COMMENT 'Type of event (e.g., "ACCESS_GRANTED", "TRANSACTION_INITIATED")',
`user_id` INT UNSIGNED NULL COMMENT 'User associated with the event, if applicable',
`resource_id` VARCHAR(255) NULL COMMENT 'Identifier of the resource affected',
`details` JSON NULL COMMENT 'Structured details of the event',
`timestamp` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp of event occurrence',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX `idx_event_type` (`event_type`),
INDEX `idx_timestamp` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Key considerations here include:
ticket_uuid: A UUID ensures uniqueness across distributed systems and aids in cross-referencing.event_type: Categorizes the event for filtering and reporting.details(JSON): Allows for flexible, structured data capture without schema rigidity for every event variation.- Timestamps: Essential for chronological ordering and auditability.
PHP Implementation with mPDF
We will use PHP to query the event ticket register and then use mPDF to render a compliant PDF report. mPDF is a powerful PHP library for generating PDF files from HTML and CSS. It supports UTF-8, complex layouts, and custom fonts, making it suitable for professional reporting.
Installation of mPDF
The recommended installation method is via Composer:
composer require mpdf/mpdf
Generating the PDF Report
The following PHP script demonstrates how to fetch data and generate a PDF report. This example assumes a basic PDO connection for database interaction.
<?php
require_once __DIR__ . '/vendor/autoload.php'; // Adjust path as necessary
use Mpdf\Mpdf;
use Mpdf\MpdfException;
// --- Database Configuration ---
$dbHost = 'localhost';
$dbName = 'your_database_name';
$dbUser = 'your_db_user';
$dbPass = 'your_db_password';
$dbCharset = 'utf8mb4';
$dsn = "mysql:host=$dbHost;dbname=$dbName;charset=$dbCharset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $dbUser, $dbPass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
// --- Report Generation Parameters ---
$startDate = '2023-01-01 00:00:00'; // Example start date
$endDate = '2023-12-31 23:59:59'; // Example end date
$eventTypeFilter = null; // e.g., 'ACCESS_GRANTED' or null for all
// --- Fetch Data from Database ---
$sql = "SELECT
ticket_uuid,
event_type,
user_id,
resource_id,
details,
timestamp
FROM event_tickets
WHERE timestamp BETWEEN :start_date AND :end_date";
$params = [':start_date' => $startDate, ':end_date' => $endDate];
if ($eventTypeFilter !== null) {
$sql .= " AND event_type = :event_type";
$params[':event_type'] = $eventTypeFilter;
}
$sql .= " ORDER BY timestamp ASC";
try {
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$tickets = $stmt->fetchAll();
} catch (\PDOException $e) {
// Log error and handle gracefully
die("Database error: " . $e->getMessage());
}
// --- Prepare HTML Content for PDF ---
$html = '<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Ticket Register Report</title>
<style>
body { font-family: "dejavusans", sans-serif; font-size: 10pt; }
h1 { text-align: center; color: #333; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.details-json { font-family: "courier new", monospace; font-size: 8pt; white-space: pre-wrap; word-break: break-all; }
.footer { position: fixed; bottom: 0; width: 100%; text-align: center; font-size: 8pt; color: #777; }
</style>
</head>
<body>
<h1>Event Ticket Register Report</h1>
<p><strong>Report Period:</strong> ' . htmlspecialchars($startDate) . ' to ' . htmlspecialchars($endDate) . '</p>';
if ($eventTypeFilter !== null) {
$html .= '<p><strong>Event Type Filter:</strong> ' . htmlspecialchars($eventTypeFilter) . '</p>';
}
$html .= '<table>
<thead>
<tr>
<&th>Timestamp</th>
<th>Event Type</th>
<th>User ID</th>
<th>Resource ID</th>
<th>Details</th>
</tr>
</thead>
<tbody>';
if (empty($tickets)) {
$html .= '<tr><td colspan="5" style="text-align:center;">No records found for the specified period.</td></tr>';
} else {
foreach ($tickets as $ticket) {
$html .= '<tr>
<td>' . htmlspecialchars($ticket['timestamp']) . '</td>
<td>' . htmlspecialchars($ticket['event_type']) . '</td>
<td>' . ($ticket['user_id'] ?? 'N/A') . '</td>
<td>' . htmlspecialchars($ticket['resource_id'] ?? 'N/A') . '</td>
<td class="details-json">' . htmlspecialchars(json_encode(json_decode($ticket['details'], true), JSON_PRETTY_PRINT)) . '</td>
</tr>';
}
}
$html .= '</tbody>
</table>
<div class="footer">Generated on: ' . date('Y-m-d H:i:s') . ' | Confidential</div>
</body>
</html>';
// --- Initialize mPDF ---
try {
$mpdf = new Mpdf([
'mode' => 'utf-8',
'format' => 'A4-P', // Portrait A4
'margin_left' => 15,
'margin_right' => 15,
'margin_top' => 25,
'margin_bottom' => 25,
'margin_header' => 10,
'margin_footer' => 10,
'default_font_size' => 10,
'default_font' => 'dejavusans', // Ensure this font is available or configured
'tempDir' => sys_get_temp_dir() . '/mpdf_temp' // Specify a writable temp directory
]);
// Set header and footer
$mpdf->SetHTMLHeader('<div style="text-align: right; font-weight: bold;">Event Ticket Register Report</div>');
$mpdf->SetHTMLFooter('<div style="text-align: center; font-size: 8pt;">Page {PAGENO} of {nbpg} | Generated on: ' . date('Y-m-d H:i:s') . '</div>');
// Write the HTML content
$mpdf->WriteHTML($html);
// Output the PDF
// For download:
$mpdf->Output('event_ticket_report_' . date('Ymd_His') . '.pdf', 'D');
// For saving to a file:
// $mpdf->Output('reports/event_ticket_report_' . date('Ymd_His') . '.pdf', 'F');
} catch (MpdfException $e) {
// Log error and handle gracefully
die("PDF generation error: " . $e->getMessage());
}
?>
Configuration and Customization
Several aspects of the report generation can be customized:
- Date Range and Filters: The
$startDate,$endDate, and$eventTypeFiltervariables allow for dynamic report generation based on specific criteria. These can be passed as GET/POST parameters for a web-based interface. - Database Credentials: Ensure the database connection details are securely managed, ideally using environment variables or a configuration file outside the web root.
- mPDF Configuration: The
Mpdfconstructor accepts an array of configuration options. Key ones include:'mode': ‘utf-8’ is standard.'format': ‘A4-P’ for portrait, ‘A4-L’ for landscape.- Margins: Control spacing around content.
'default_font': Crucial for displaying special characters correctly. Ensure the font (e.g., ‘dejavusans’) is installed and accessible by mPDF. You might need to configure mPDF’s font directory.'tempDir': A writable directory for temporary files is essential.
- HTML/CSS Styling: The embedded CSS provides basic formatting. For more complex layouts, external CSS files can be referenced, or mPDF’s advanced features like page breaks and headers/footers can be leveraged. The
.details-jsonclass demonstrates styling for the JSON data to improve readability. - Output Method:
'D'forces a download,'F'saves to a file, and'I'sends inline to the browser.
Security and Best Practices
When implementing automated reporting, especially for sensitive data, adhere to these practices:
- Input Validation: If report parameters (dates, filters) are user-supplied, rigorously validate and sanitize them to prevent SQL injection or other vulnerabilities. Use prepared statements (as shown) for database queries.
- Access Control: Restrict access to the report generation script. Implement authentication and authorization mechanisms to ensure only authorized personnel can generate or view these reports.
- Secure Storage: If reports are saved to files, ensure the storage location is secured with appropriate file system permissions and is not publicly accessible.
- Error Handling and Logging: Implement comprehensive error handling and logging for both database operations and PDF generation. This is critical for debugging and auditing.
- Temporary Directory Permissions: The directory specified for
'tempDir'in mPDF must be writable by the web server process. Ensure this directory is not publicly accessible. - Font Management: For consistent rendering across different environments, consider bundling necessary fonts with your application or ensuring they are installed on the server.
Automating Report Generation
To fully automate compliance reporting, consider integrating this script into a scheduled task:
- Cron Jobs (Linux/macOS): Use cron to execute the PHP script at regular intervals. You can pass parameters via the command line.
# Example cron entry to generate a daily report at 2 AM 0 2 * * * /usr/bin/php /path/to/your/report_script.php --start-date=$(date -d "yesterday" +"%Y-%m-%d 00:00:00") --end-date=$(date -d "yesterday" +"%Y-%m-%d 23:59:59") --output-dir=/path/to/save/reports
- Task Scheduler (Windows): Similar functionality using Windows Task Scheduler.
- CI/CD Pipelines: Integrate report generation into your CI/CD pipeline for on-demand or scheduled report creation as part of deployment or maintenance tasks.
- API Endpoint: Expose the script as a secure API endpoint that can be triggered by other systems or manually via a dashboard.
When using command-line arguments, modify the PHP script to parse them using `getopt()` or a library like Symfony’s Console component.
Conclusion
By combining a robust event ticket register with the mPDF library, organizations can establish an automated, auditable, and professional reporting mechanism. This solution provides a tangible way to meet compliance requirements, offering clear visibility into critical system events and transactions in a universally accessible PDF format.