習慣 ASP.NET WebForms 開發的程式員常覺得 PHP 缺乏「頁面生命週期」與「按鈕點擊事件」模型。本文實現一個輕量級 EventHelper.php,模擬 Page_Load、IsPostBack、Button_Click 等核心機制,讓 PHP 頁面也能用事件驅動風格編寫。
<?php
require_once '../inc/EventHelper.php';
function Page_Load() {
echo '在任何時候都會運行<br>';
if (!Page::IsPostBack()) {
echo '加載產品分類<br>';
if ($_GET['cmd'] == 'edit') {
echo '修改加載需要修改的產品信息<br>';
}
}
}
function bAdd_Click() {
echo "bAdd_Click<br>";
}
function bEdit_Click() {
echo 'proID=' . $_GET['proID'] . '<br>';
echo "bEdit_Click<br>";
}
function sdfsdfdsf_Click() {
echo "e44444444444444444444<br>";
}
?>
<form name="aa" method="post" action="?<?=Comm::GetParam()?>">
<input type="submit" name="bAdd" value="添加" />
<input type="submit" name="bEdit" value="修改" />
<input type="submit" name="sdfsdfdsf" value="ewrewrewr" />
</form>
<?php
class Page {
// 判斷是否為 PostBack(有按鈕提交)
public static function IsPostBack() {
global $SYSRunEventName;
return !empty($SYSRunEventName);
}
// 事件加載與分發
public static function EventLoad() {
global $SYSRunEventName;
// 獲取所有用戶定義函數
$arrEvent = get_defined_functions();
$arrEventUser = $arrEvent['user'];
// 遍歷 $_POST 找出被點擊的按鈕
$arr = array_keys($_POST);
foreach ($arr as $row) {
$name = strtolower($row);
foreach ($arrEventUser as $row1) {
$name1 = str_ireplace('_click', '', $row1);
if ($name == $name1) {
$SYSRunEventName = $row1; // 記錄要執行的事件函數名
break;
}
}
if (!empty($SYSRunEventName)) break;
}
// 1. 永遠執行 Page_Load
if (function_exists('Page_Load')) Page_Load();
// 2. 若是 PostBack,執行對應的 XXX_Click
$SYSRunEventRunName = strtolower($SYSRunEventName);
if (Page::IsPostBack()) {
$SYSRunEventName(); // 動態調用函數
}
}
}
class Comm {
// 智能構建 URL 參數:保留現有 GET、覆蓋/新增指定參數
public static function GetParam($params = [], $cmd = 'addoverride') {
$allParam = [];
if ($cmd == 'addoverride') {
foreach (array_keys($params) as $row) {
if (!in_array($row, array_keys($allParam))) $allParam[$row] = $params[$row];
}
} elseif ($cmd == 'del') {
foreach ($params as $row) unset($_GET[$row]);
}
foreach (array_keys($_GET) as $row) {
if (!in_array($row, array_keys($allParam))) $allParam[$row] = $_GET[$row];
}
$p = '';
foreach (array_keys($allParam) as $row) $p .= $row . '=' . $allParam[$row] . '&';
return rtrim($p, '&');
}
}
// 自動啟動事件分發
Page::EventLoad();
?>
<input type="submit" name="bAdd"> 被點擊時,瀏覽器會將 bAdd=添加 放入 $_POSTEventLoad 遍歷 $_POST 鍵名,去掉 _click 後綴,匹配用戶定義的 bAdd_Click 函數Page_Load 永遠執行 → IsPostBack() 判斷 → 執行對應 XXX_Clickget_defined_functions() 獲取所有用戶函數,function_exists() 安全調用$_POST 鍵名動態調用函數,若攻擊者構造 _POST['eval'] = ... 可能觸發危險函數(需白名單過濾)// 在 EventLoad 中增加白名單檢查
$allowedEvents = ['bAdd_Click', 'bEdit_Click', 'sdfsdfdsf_Click'];
if (!in_array($SYSRunEventName, $allowedEvents)) {
$SYSRunEventName = '';
}
// 或使用前綴約定:只有以 _Click 結尾且前綴在白名單中的才允許執行
生產環境建議遷移至成熟框架(Laravel、ThinkPHP、Symfony)使用控制器/路由機制。