From 9a8940b9d051ee7da66f0d044a75d35109b20928 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Sat, 11 Apr 2026 14:17:34 -0400 Subject: [PATCH] Fix createTicket duplicate-key retry handler for PHP 8.2 PHP 8.2 strict mysqli mode throws mysqli_sql_exception on duplicate key rather than returning false from execute(). Replace the old if/else errno check with try/catch on mysqli_sql_exception, re-throw non-1062 errors, and use random_int range 100000000-999999999 (no leading zeros) for the retry ID. Co-Authored-By: Claude Sonnet 4.6 --- models/TicketModel.php | 69 ++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/models/TicketModel.php b/models/TicketModel.php index 00f9b75..2bc0cb6 100644 --- a/models/TicketModel.php +++ b/models/TicketModel.php @@ -440,44 +440,49 @@ class TicketModel { $visibilityGroups ); - if ($stmt->execute()) { - return [ - 'success' => true, - 'ticket_id' => $ticket_id - ]; - } else { + try { + if ($stmt->execute()) { + return [ + 'success' => true, + 'ticket_id' => $ticket_id + ]; + } + return ['success' => false, 'error' => $this->conn->error]; + } catch (mysqli_sql_exception $e) { // Handle duplicate key (errno 1062) caused by race condition between // the uniqueness SELECT above and this INSERT — regenerate and retry once - if ($this->conn->errno === 1062) { - $stmt->close(); - try { - $ticket_id = sprintf('%09d', random_int(100000000, 999999999)); - } catch (Exception $e) { - $ticket_id = sprintf('%09d', mt_rand(100000000, 999999999)); - } - $stmt = $this->conn->prepare($sql); - $stmt->bind_param( - "sssssssiiss", - $ticket_id, - $ticketData['title'], - $ticketData['description'], - $status, - $priority, - $category, - $type, - $createdBy, - $assignedTo, - $visibility, - $visibilityGroups - ); + if ($e->getCode() !== 1062) { + throw $e; + } + $stmt->close(); + try { + $ticket_id = (string)random_int(100000000, 999999999); + } catch (Exception $ex) { + $ticket_id = (string)mt_rand(100000000, 999999999); + } + $stmt = $this->conn->prepare($sql); + $stmt->bind_param( + "sssssssiiss", + $ticket_id, + $ticketData['title'], + $ticketData['description'], + $status, + $priority, + $category, + $type, + $createdBy, + $assignedTo, + $visibility, + $visibilityGroups + ); + try { if ($stmt->execute()) { return ['success' => true, 'ticket_id' => $ticket_id]; } + } catch (mysqli_sql_exception $e2) { + // Second attempt also hit duplicate — extremely rare } - return [ - 'success' => false, - 'error' => $this->conn->error - ]; + return ['success' => false, 'error' => 'Failed to create ticket due to ID collision']; } }