PHP中如何获取__LINE__常量调用处的行号而非定义处行号
问题本质
这个问题的本质是PHP的魔术常量__LINE__、__CLASS__属于编译期常量,代码解析时就会被替换成对应代码所在位置的字面量,所以定义在log_suffix方法内的常量,永远只会返回方法定义处的行号和类名,和调用位置无关。
除了try catch捕获异常的方案外,还有两种更常用的解决方案:
方案1:使用debug_backtrace()获取调用栈信息
PHP内置的debug_backtrace()函数可以获取当前代码的调用栈信息,不需要抛出异常就能拿到调用方的类、行号、文件路径等信息,是这类场景的最优解:
function log_suffix(){ // 仅获取前2层栈信息、忽略调用参数,降低性能消耗 $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); // 索引0为当前log_suffix方法的栈帧,索引1为调用log_suffix的位置的栈帧 $caller = $trace[1]; $callClass = $caller['class'] ?? __CLASS__; $callLine = $caller['line'] ?? __LINE__; return "{$this->company_code} | {$this->company_name} on File: {$callClass} Line: {$callLine}"; }
该方案不需要修改原有调用逻辑,仅修改log_suffix内部实现即可,普通业务场景下的性能损耗可以忽略不计。
方案2:调用时传入魔术常量作为参数
如果是高并发生产环境,想要完全避免debug_backtrace()的性能开销,可以微调方法设计,调用时传入对应位置的魔术常量即可:
// 修改log_suffix接收两个参数 function log_suffix(string $callClass, int $callLine){ return "{$this->company_code} | {$this->company_name} on File: {$callClass} Line: {$callLine}"; } // 调用时传入当前位置的常量即可 Log::error("log: " . $this->log_suffix(__CLASS__, __LINE__) );// Line 39
该方案性能最高,结果100%准确,缺点是每次调用都需要传入两个魔术常量,但相比每次手动拼接完整的日志后缀,仍然大幅减少了重复代码。
内容的提问来源于stack exchange,提问作者Nasik Ahd
相关产品推荐
相关产品推荐

