在企業內部系統開發中,常需從考勤機、POS 系統等裝置匯出 CSV 檔案,並批次匯入資料庫。本文示範如何在 FleaPHP 框架下建立完整的 CSV 上傳、驗證、解析、入庫流程,包含檔案型態檢查、編碼轉換、業務邏輯判斷與錯誤處理。
<?php
class Controller_KaoqinUpload extends FLEA_Controller_Action {
var $uploaddir = "./uploadfiles/";
public function __construct() {
parent::__construct();
}
// 首頁顯示上傳表單
function actionIndex() {
$smarty =& $this->_getView();
$smarty->display("kaoqin_upload.html");
}
// 驗證檔名是否符合 Y-m-d 格式
private function isDate($file_name) {
$filename = explode('.', $file_name);
$real_name = $filename[count($filename)-2];
$format = "Y-m-d";
$unixTime = strtotime($real_name);
$checkDate = date($format, $unixTime);
return ($real_name == $checkDate);
}
// 處理上傳與匯入邏輯
public function actionSave() {
$upload_file = $_FILES['upload_file'];
// ... 檔案基本驗證(大小、類型、重複檢查)...
// 讀取 CSV 內容(支援分號分隔)
$data = file($upload_file['tmp_name']);
$attendance =& get_singleton('Model_attendance');
// 逐行解析(跳過標題行與空行)
for ($i = 1; $i < count($data) - 1; $i++) {
$fields = explode(";", $data[$i]);
// 編碼轉換:GB2312 → UTF-8
foreach ([0,1,2,4,5] as $idx) {
$fields[$idx] = iconv("gb2312", "utf-8", $fields[$idx]);
}
// 組裝資料陣列
$record = [
"ATTENDANCE_FINGERPRINT_ID" => intval(trim($fields[0], '"/')),
"ATTENDANCE_USER_NAME" => trim($fields[1], '"/'),
"ATTENDANCE_DATE" => trim($fields[2], '"/'),
"ATTENDANCE_GO_WORK" => trim($fields[4], '"/'),
"ATTENDANCE_AFTER_WORK" => trim($fields[5], '"/'),
];
// 判斷打卡狀態:1正常 2遲到 3早退 4缺勤
$go = $record["ATTENDANCE_GO_WORK"];
$off = $record["ATTENDANCE_AFTER_WORK"];
if (strlen($go)==0 && strlen($off)!=0) $record["ATTENDANCE_STATUS"] = "1";
elseif (strlen($go)!=0 && strlen($off)==0) $record["ATTENDANCE_STATUS"] = "2";
elseif (strlen($go)!=0 && strlen($off)!=0) $record["ATTENDANCE_STATUS"] = "3";
else $record["ATTENDANCE_STATUS"] = "4";
// 依規則補齊缺失打卡時間
if ($record["ATTENDANCE_STATUS"] == "4") { $go = "24:00"; $off = "00:00"; }
elseif ($record["ATTENDANCE_STATUS"] == "1") { $go = "08:35"; }
elseif ($record["ATTENDANCE_STATUS"] == "2") { $off = "17:30"; }
$record["ATTENDANCE_GO_WORK"] = $go;
$record["ATTENDANCE_AFTER_WORK"] = $off;
// 計算在勤時長(時:分)
list($gh, $gm) = explode(":", $go);
list($oh, $om) = explode(":", $off);
$diffMin = $om - $gm;
$diffHour = $oh - $gh;
if ($diffMin < 0) { $diffHour--; $diffMin += 60; }
if ($diffHour < 0) $diffHour += 24;
$record["ATTENDANCE_TIME"] = sprintf("%02d:%02d", $diffHour, $diffMin);
if ($record["ATTENDANCE_TIME"] == "-1:00") $record["ATTENDANCE_TIME"] = "00:00";
// 寫入資料庫
$attendance->create($record);
}
// 檔案備份與結果回饋
move_uploaded_file($upload_file['tmp_name'], $this->uploaddir.$upload_file['name']);
echo "考勤資料更新成功<br>";
}
}
?>
.csv、MIME 為 application/vnd.ms-excelYYYY-MM-DD.csv 格式,避免誤上傳考勤機常以 GB2312 輸出,系統採 UTF-8,使用 iconv() 逐欄位轉碼,防止中文亂碼。
根據上/下班打卡缺漏組合,自動歸類四種狀態,並依公司規定補齊預設工時(如遲到按 08:35 計、早退按 17:30 計),確保薪資計算基準一致。
時間差計算邏輯處理了跨日情況(如 23:00~07:00),若時差為負則加 24 小時,確保時長正確。
本範例展示了在 FleaPHP 中處理 CSV 匯入的完整流程,從檔案接收、驗證、解析、業務邏輯到入庫,涵蓋實務中常見的編碼、時間計算、異常處理等細節,可直接套用至考勤、薪資、庫存等批次匯入場景。