早期 PHP 缺乏統一的數據庫抽象層,調試手段匱乏。本文整理了一套實用的通用函數庫,涵蓋數據庫統一操作、變量可視化調試、分級日誌記錄、代碼性能計時、SQL 執行監控五大模塊,代碼經典且思想通用,適合理解 PHP 底層機制與框架設計思想。
封裝 mysql_* / mssql_* 等特定擴展,暴露統一接口 query(), next_record() 等,屏蔽底層差異。現代開發請直接使用 PDO 或 Doctrine DBAL。
遞歸輸出任意變量(標量、數組、對象)的類型、結構與值,解決無 IDE 調試環境下的可視化難題。
function ss_as_string(&$thing, $column = 0) {
if (is_object($thing)) return ss_object_as_string($thing, $column);
elseif (is_array($thing)) return ss_array_as_string($thing, $column);
elseif (is_double($thing)) return "Double($thing)";
elseif (is_long($thing)) return "Long($thing)";
elseif (is_string($thing)) return "String($thing)";
else return "Unknown($thing)";
}
function ss_array_as_string(&$array, $column = 0) {
$str = "Array\n";
foreach ($array as $var => $val) {
$str .= str_repeat(" ", $column + 1) . "$var => " . ss_as_string($val, $column + 1) . "\n";
}
$str .= str_repeat(" ", $column) . ")";
return $str;
}
// 使用示例
echo ss_as_string($my_variable); // 查看單個變量
echo ss_as_string($GLOBALS); // 查看所有全局變量
四級日誌:NONE(0) < ERROR(1) < INFO(2) < DEBUG(3)。運行時動態設置級別,僅記錄 ≥ 當前級別的信息。
$ss_log_level = 0; // 當前級別
$ss_log_filename = '/tmp/ss-log';
$ss_log_levels = ['NONE'=>0, 'ERROR'=>1, 'INFO'=>2, 'DEBUG'=>3];
function ss_log_set_level($level = 'ERROR') {
global $ss_log_level;
$ss_log_level = $ss_log_levels[$level];
}
function ss_log($level, $message) {
global $ss_log_level, $ss_log_filename, $ss_log_levels;
if ($ss_log_levels[$ss_log_level] < $ss_log_levels[$level]) return false; // 級別不夠,丟棄
$fd = fopen($ss_log_filename, 'a+');
fputs($fd, "$level - [" . ss_timestamp_pretty() . "] - $message\n");
fclose($fd);
return true;
}
function ss_log_reset() {
global $ss_log_filename;
@unlink($ss_log_filename);
}
// 使用示例
ss_log_set_level('INFO'); // 僅記錄 ERROR 和 INFO
ss_log('ERROR', 'Database connection failed');
ss_log('DEBUG', 'Query executed'); // 不會被記錄
支持多計時器並發,基於 microtime() 實現微秒級精度。
function ss_timing_start($name = 'default') {
global $ss_timing_start_times;
$ss_timing_start_times[$name] = explode(' ', microtime());
}
function ss_timing_stop($name = 'default') {
global $ss_timing_stop_times;
$ss_timing_stop_times[$name] = explode(' ', microtime());
}
function ss_timing_current($name = 'default') {
global $ss_timing_start_times, $ss_timing_stop_times;
if (!isset($ss_timing_start_times[$name])) return 0;
$stop_time = isset($ss_timing_stop_times[$name]) ? $ss_timing_stop_times[$name] : explode(' ', microtime());
$current = ($stop_time[1] - $ss_timing_start_times[$name][1]) + ($stop_time[0] - $ss_timing_start_times[$name][0]);
return $current;
}
// 使用示例
ss_timing_start('query');
// ... 執行 SQL ...
ss_timing_stop('query');
echo "Query took: " . ss_timing_current('query') . " seconds";
結合計時與日誌,自動記錄每條 SQL 耗時與語句,定位慢查詢。
function query($Query_String, $halt_on_error = 1) {
$this->connect();
ss_timing_start();
$this->Query_ID = @mysql_query($Query_String, $this->Link_ID);
ss_timing_stop();
// 記錄耗時 + SQL 語句,級別 INFO
ss_log('INFO', ss_timing_current() . " Secs - " . $Query_String);
$this->Row = 0;
$this->Errno = mysql_errno();
$this->Error = mysql_error();
if ($halt_on_error && !$this->Query_ID) {
$this->halt("Invalid SQL: " . $Query_String);
}
return $this->Query_ID;
}
| 功能 | 經典方案 | 現代最佳實踐 |
|---|---|---|
| 數據庫抽象 | 自封裝函數 | PDO (原生)、Doctrine DBAL、Laravel Eloquent (ORM) |
| 變量調試 | ss_as_string() | var_dump()、Symfony VarDumper、Xdebug + IDE 斷點調試 |
| 日誌記錄 | 自寫文件日誌 | Monolog (PSR-3)、Laravel Log、Sentry (異常追蹤) |
| 性能分析 | microtime 計時 | Xdebug Profiler、Blackfire.io、Laravel Telescope |
| SQL 監控 | 手動記錄 | DBAL SQLLogger、MySQL Slow Query Log、Pt-query-digest |
理解這些基礎函數的實現原理,有助於深入掌握框架底層運行機制,在排查疑難雜癥、設計高性能系統時更具洞察力。