Skip to content

代码调试技巧

调试是开发中必不可少的技能,本文介绍 PHP 中常用的调试方法。

基础调试输出

php
// print_r 和 var_dump
$arr = ['a' => 1, 'b' => 2];
print_r($arr);
var_dump($arr);  // 更详细,包含类型信息

// 格式化输出
var_export($arr);  // 可直接作为 PHP 代码使用

// 输出并终止(最常用)
var_dump($data);
die();  // 或 exit()

// 美化 var_dump(需要 Xdebug)
ini_set('xdebug.var_display_max_depth', 10);
ini_set('xdebug.var_display_max_children', 256);
ini_set('xdebug.var_display_max_data', 1024);

日志调试

php
// 错误日志
error_log('调试信息');
error_log('变量值: ' . print_r($var, true));

// 自定义日志函数
function debug_log($message, $data = null) {
    $log = [
        'time' => date('Y-m-d H:i:s'),
        'file' => debug_backtrace()[0]['file'],
        'line' => debug_backtrace()[0]['line'],
        'message' => $message,
        'data' => $data
    ];
    error_log(json_encode($log, JSON_UNESCAPED_UNICODE) . "\n", 3, '/tmp/debug.log');
}

// 使用
debug_log('用户登录', ['user_id' => 123]);

调试函数

php
// 获取调用栈
debug_print_backtrace();

// 获取更详细的信息
$trace = debug_backtrace();
foreach ($trace as $frame) {
    echo $frame['file'] . ':' . $frame['line'] . ' ' . $frame['function'] . "\n";
}

// 获取内存使用
echo memory_get_usage() . " bytes\n";
echo memory_get_peak_usage() . " bytes\n";

// 获取执行时间
$start = microtime(true);
// ... 代码 ...
echo '耗时: ' . (microtime(true) - $start) . ' 秒';

断点调试(Xdebug)

php
// 触发断点
xdebug_break();

// 配置 php.ini
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=localhost
xdebug.client_port=9003
xdebug.idekey=PHPSTORM

使用 VS Code + PHP Debug 扩展:

  1. 安装 PHP Debug 扩展
  2. 创建 .vscode/launch.json 配置
  3. 设置断点并按 F5 启动调试
json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003
        }
    ]
}

调试工具类

php
class Debugger {
    private static $timers = [];
    private static $logs = [];

    // 开始计时
    public static function start($name) {
        self::$timers[$name] = microtime(true);
    }

    // 结束计时
    public static function end($name) {
        if (!isset(self::$timers[$name])) return null;
        $time = microtime(true) - self::$timers[$name];
        unset(self::$timers[$name]);
        return round($time * 1000, 2) . 'ms';
    }

    // 记录变量
    public static function log($key, $value) {
        self::$logs[$key] = $value;
    }

    // 显示所有调试信息
    public static function dump() {
        echo "<pre style='background:#333;color:#fff;padding:10px;'>";
        echo "=== Debug Output ===\n\n";
        foreach (self::$logs as $key => $value) {
            echo "[$key]:\n";
            var_export($value);
            echo "\n\n";
        }
        echo "</pre>";
    }
}

// 使用
Debugger::start('query');
$result = $db->query($sql);
Debugger::end('query');
Debugger::log('result', $result);
Debugger::dump();

异常调试

php
try {
    $result = riskyOperation();
} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
    echo "文件: " . $e->getFile() . "\n";
    echo "行号: " . $e->getLine() . "\n";
    echo "堆栈:\n" . $e->getTraceAsString() . "\n";
}

注意事项

  1. 生产环境不要暴露 display_errors
  2. 调试代码要及时清理,不要提交到版本控制
  3. 使用日志文件调试 API 接口
  4. 复杂问题使用 Xdebug 断点调试更高效

Binstork