<?php
/**
* 顯示訊息並可選跳轉
* @param string $msg 提示文字
* @param string $url 跳轉網址;'back'=上一頁,''=不跳轉
* @param int $seconds 自動跳轉秒數(0=不自動跳轉)
* @param string $type 訊息類型:success/error/warning/info
* @param bool $ajax 是否為 AJAX 請求(回傳 JSON)
* @return void|string
*/
function showMsg(string $msg, string $url = '', int $seconds = 3, string $type = 'info', bool $ajax = false)
{
$types = ['success'=>'#27ae60', 'error'=>'#e74c3c', 'warning'=>'#f39c12', 'info'=>'#3498db'];
$color = $types[$type] ?? $types['info'];
$icon = ['success'=>'✅','error'=>'❌','warning'=>'⚠️','info'=>'ℹ️'][$type] ?? 'ℹ️';
if ($ajax) {
header('Content-Type: application/json');
echo json_encode([
'status' => $type === 'error' ? 'error' : 'success',
'message' => $msg,
'redirect' => $url,
'delay' => $seconds * 1000,
], JSON_UNESCAPED_UNICODE);
exit;
}
// 解析跳轉目標
$jsUrl = match ($url) {
'back' => "history.back()",
'' => 'null',
default => "location.href = '$url'",
};
$html = <<<HTML
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>系統提示</title>
<style>
body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f5f6fa}
.box{background:#fff;padding:2rem;border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,.1);text-align:center;max-width:90%;width:400px}
.icon{font-size:3rem;margin-bottom:1rem}
.msg{font-size:1.1rem;color:#2c3e50;margin-bottom:1.5rem}
.btn{display:inline-block;padding:.6rem 1.5rem;background:$color;color:#fff;border:none;border-radius:4px;cursor:pointer;text-decoration:none}
.countdown{margin-top:1rem;color:#7f8c8d;font-size:.9rem}
</style></head><body>
<div class="box">
<div class="icon">$icon</div>
<div class="msg">$msg</div>
HTML;
if ($url !== '') {
$html .= <<<HTML
<a class="btn" href="#" onclick="$jsUrl;return false;">立即前往</a>
<div class="countdown" id="cd"></div>
<script>
var sec = $seconds, url = $jsUrl;
var el = document.getElementById('cd');
function tick() {
if (sec <= 0) { if (url !== 'null') eval(url); return; }
el.textContent = sec + ' 秒後自動跳轉...';
sec--; setTimeout(tick, 1000);
}
tick();
</script>
HTML;
}
$html .= '</div></body></html>';
echo $html;
exit;
}
<?php
// 一般表單提交後
showMsg('資料儲存成功!', 'list.php', 3, 'success');
// 錯誤攔截
showMsg('輸入格式錯誤', 'back', 0, 'error'); // 不自動跳轉,顯示「立即返回」按鈕
// AJAX 回傳
if ($_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') {
showMsg('刪除完成', '', 0, 'success', true); // 回傳 JSON
}
// 純提示不跳轉
showMsg('這是一個提示訊息', '', 0, 'info');
abstract class BaseController
{
protected function success($msg, $url = '', $sec = 3) { showMsg($msg, $url, $sec, 'success'); }
protected function error($msg, $url = 'back', $sec = 0) { showMsg($msg, $url, $sec, 'error'); }
protected function ajaxSuccess($msg, $data = []) {
header('Content-Type: application/json');
echo json_encode(array_merge(['status'=>'success','message'=>$msg], $data), JSON_UNESCAPED_UNICODE);
exit;
}
protected function ajaxError($msg, $code = 400) {
http_response_code($code);
header('Content-Type: application/json');
echo json_encode(['status'=>'error','message'=>$msg], JSON_UNESCAPED_UNICODE);
exit;
}
}
<style> 移至外部 CSS,使用 .msg-box.success、.msg-box.error 等類別控制顏色。@keyframes fadeIn)提升體驗。| 特性 | 說明 |
|---|---|
| 單一入口 | 全專案統一呼叫 showMsg(),風格一致 |
| 雙模式 | 同一函式支援頁面跳轉與 AJAX JSON 回傳 |
| 零依賴 | 純 PHP + 內嵌 CSS/JS,無需外部庫 |
| 可擴充 | 易於加入日誌記錄、多語系、主題切換 |
這個函式已服務多個專案超過 5 年,是處理使用者回饋最簡潔可靠的方式之一。