获取在PHP中执行当前函数的代码行和文件?

Tom*_*Tom 57 php

想象一下我有以下情况:

File1.php

<?php
 include("Function.php");
 log("test");
?>
Run Code Online (Sandbox Code Playgroud)

Function.php

<?php
 function log($msg)
 {
  echo "";
 }
?>
Run Code Online (Sandbox Code Playgroud)

我想更改日志功能,以便它将产生以下内容:

test(文件:File1.php,行号:3)

那么,以何种方式获取PHP中执行当前函数的代码的文件名和行号?

编写积压使用注释:当我以面向对象的编程方式使用backlog时,我有以下情况.

的index.php

<?php
 include("Logger.static.php");
 include("TestClass.class.php");
 new TestClass();
?>
Run Code Online (Sandbox Code Playgroud)

TestClass.class.php

<?php
 class TestClass
 {
   function __construct()
   {
     Logger::log("this is a test log message");
   }
 }
?>
Run Code Online (Sandbox Code Playgroud)

Logger.static.php

<?php
 class Logger
 {
   static public function log($msg)
   {
     $bt = debug_backtrace();
     $caller = array_shift($bt);
     echo $caller['file'];
     echo $caller['line'];
   }
 }
?>
Run Code Online (Sandbox Code Playgroud)

此示例将作为文件"Index.php"返回,并作为第4行返回,这是启动类的位置.但是,它应该返回文件TestClass.class.php和第6行.任何想法如何解决这个问题?

Lio*_*hen 91

您可以使用debug_backtrace().

http://us3.php.net/manual/en/function.debug-backtrace.php

因此,在您的日志功能中,您将能够检索调用日志函数的文件名和行号.

我在我的日志记录类中使用这种方法,它显着减少了获取有意义的日志数据所需的代码量.另一个好处是可读性.当与弦乐混合时,魔术常数会变得非常难看.

这是一个简单的例子:

function log($msg)
{
  $bt = debug_backtrace();
  $caller = array_shift($bt);

  // echo $caller['file'];
  // echo $caller['line'];

  // do your logging stuff here.    
}
Run Code Online (Sandbox Code Playgroud)

  • 从PHP 5.4.0开始,您可以使用`debug_backtrace()`发送一个参数来限制返回的堆栈帧数.在这个用例中使用`debug_backtrace(1)`在性能方面可能是一个好主意. (5认同)
  • 实际上,有一个问题。我正在以一种面向对象的方式进行编码,它返回的行和脚本正在调用在其中调用函数的对象。相反,它应该给我包含类的名称以及该类文件中的行。任何的想法? (2认同)
  • 我很惊讶。它确实有效。我确信我昨天测试过它,它似乎给了我错误的结果。嗯,对此感到抱歉。不知道出了什么问题,但现在可以了。 (2认同)
  • 一个小错误@Ivar,应该是:debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1)。第一个参数允许以下选项的位掩码:DEBUG_BACKTRACE_PROVIDE_OBJECT、DEBUG_BACKTRACE_IGNORE_ARGS。 (2认同)

zom*_*bat 27

debug_backtrace()可用于追溯调用堆栈.虽然它可能很慢,但如果你做了大量的日志记录,请小心.

如果你正在使用PHP 5.3,你可以利用后期静态绑定并拥有一个基类方法log(),你的子类可以调用它,但仍然保持对__FILE__和的静态引用__LINE__.

当你调用你的函数时,最后一个选项就是传递__FILE____LINE__作为参数log().