I always get an error message ‘There is no active transaction’. I already checked $connection->beginTransaction()
if it works or not, and the connection began. But the try catch
always catch if the transaction is not active. Here is my code
<?php
include "../../connection.php";
include "../../response.php";
include "../../function/checkhash.php";
header('Content-Type: application/json');
$value = file_get_contents('php://input');
$jsonObject = json_decode($value, true);
$connection = $connection;
$response_server = new Response();
$response = [];
$hash = $jsonObject["hash"];
$start = $jsonObject["start"];
$end = $jsonObject["end"];
$employee = $jsonObject["employee"];
$shift = $jsonObject["shift"];
$user = checkHash($connection, $hash);
if (!$user['success']) { $response = $response_server->credential();}
else {
$connection->beginTransaction();
if($connection->inTransaction()){
// $response = $response = $response_server->ok("Berhasil mengedit shift karyawan");
try {
$query = " CREATE OR REPLACE VIEW view_color AS
SELECT DISTINCT
a.fk_employee AS employee,
CAST(a.ts_start AS DATE) AS date_start,
at.v_color AS color
FROM attendance_type at
JOIN attendance a ON a.fk_attendance_type = at.i_code
WHERE CAST(a.ts_start AS DATE) BETWEEN :start AND :end AND a.b_isactive = 1";
$stmt = $connection->prepare($query);
$stmt->bindParam(":start", $start);
$stmt->bindParam(":end", $end);
$stmt->execute();
$query = "SELECT v_code_attendance FROM employee where i_code = :employee";
$stmt = $connection->prepare($query);
$stmt->execute([ ':employee' => $employee ]);
$code_attendance = $stmt->fetchColumn();
$query = " SELECT
ce.i_code AS code,
e.i_code AS employee_code,
e.v_code_attendance AS employee_code_attendance,
e.v_name AS employee_name,
s.i_code AS shift_code,
s.v_name AS shift_name,
ce.dt_calendar AS date_calendar,
ce.b_work_day AS is_work_day,
IFNULL(( SELECT color FROM view_color WHERE employee = e.i_code AND date_start = ce.dt_calendar ), 'dark') AS color
FROM calendar_employee ce
JOIN employee e ON e.i_code = ce.fk_employee
JOIN shift s ON s.i_code = ce.fk_shift
WHERE ce.b_isactive = 1
AND e.i_code = :employee
AND MONTH(ce.dt_calendar) LIKE MONTH(:start) AND YEAR(ce.dt_calendar) LIKE YEAR(:start)
AND ce.dt_calendar BETWEEN :start AND :end;";
$stmt = $connection->prepare($query);
$stmt->execute([
':start' => $start,
':end' => $end,
':employee' => $employee
]);
$shifts = $stmt->fetchAll(PDO::FETCH_ASSOC);
$datetime_start = new DateTime($start);
$datetime_end = new DateTime($end);
$interval = $datetime_start->diff($datetime_end);
$days = $interval->days + 1;
$existingDates = array_column($shifts, 'date_calendar');
$allDates = [];
for ($i = 0; $i < $days; $i++) {
$currentDate = $datetime_start->format('Y-m-d');
$allDates[] = $currentDate;
$datetime_start->modify('+1 day');
}
$missingDates = array_diff($allDates, $existingDates);
$insertQuery = "INSERT INTO calendar_employee (i_code, fk_employee, fk_shift, dt_calendar) VALUES ";
$insertValues = [];
$insertParams = [];
foreach ($missingDates as $index => $missingDate) {
// Calendar Employee's Data
$query = "SELECT ce.fk_employee, ce.dt_calendar, COUNT(*) as cnt, e.v_code_attendance as code_attendance
FROM calendar_employee ce
JOIN employee e on e.i_code = ce.fk_employee
WHERE ce.fk_employee = :employee AND DATE(ce.dt_calendar) = DATE(:date)
GROUP BY ce.fk_employee, ce.dt_calendar";
$stmt = $connection->prepare($query);
$stmt->execute([
':employee' => $employee,
':date' => $missingDate
]);
$existingData = $stmt->fetchAll(PDO::FETCH_ASSOC);
$existingCount = [];
$key = '';
foreach ($existingData as $row) {
$key = $row['fk_employee'] . '_' . $row['dt_calendar'];
$existingCount[$key] = $row['cnt'];
}
$count = isset($existingCount[$key]) ? $existingCount[$key] + 1 : 1;
$d = (new DateTime($missingDate))->format("Ymd");
$i_code = $d . $code_attendance . $count;
$insertValues[] = "(:i_code{$index}, :employee{$index}, :shift{$index}, :date{$index})";
$insertParams[":i_code{$index}"] = $i_code;
$insertParams[":employee{$index}"] = $employee;
$insertParams[":shift{$index}"] = $shift;
$insertParams[":date{$index}"] = $missingDate;
}
if (!empty($insertValues)) {
$insertQuery .= implode(', ', $insertValues);
$stmt = $connection->prepare($insertQuery);
$stmt->execute($insertParams);
}
foreach ($shifts as $item) {
$updateQuery = "UPDATE calendar_employee SET fk_shift = :shift WHERE i_code = :code";
$stmt = $connection->prepare($updateQuery);
$stmt->execute([
':shift' => $shift,
':code' => $item['code']
]);
}
$query = "INSERT INTO log_calendar_employee (fk_log_login, v_action) VALUES (:log_login, 'Insert-Update-Bulk')";
$stmt = $connection->prepare($query);
$stmt->execute([
":log_login" => $user['data']['session_code']
]);
if($connection->inTransaction()){ //if i remove this logic and just call commit() the 'no active transaction will occur'
$connection->commit();
}
$response = $response_server->ok("Berhasil mengedit shift karyawan");
} catch (Exception $e) {
error_log("Transaction start failed: " . $e->getMessage());
$response = $response_server->internalServerError("Transaction start failed: " . $e->getMessage());
echo json_encode($response);
exit;
}
}
}
echo json_encode($response);
?>
After further investigation, when I do $connection->commit()
is the cause the error of ‘no active transaction’ fired. I don’t know why is that happening. The problem is, it only happening only in this script, my other PHP script works normally with the same place where I put $connection->beginTransaction()
and where I put $connection->commit()
at the last line.