如何获取赋予当前对象的对象的类名或文件名?

时间:2009-09-02 18:24:29

标签: php oop

澄清:

我正在构建一个允许我轻松记录消息的Logger类:

lib.Logger.php:

<?php
class Logger {
    private $handle;

    public function __construct($log_name, $log_path) {

        if ( ! is_dir($log_path))
            throw new Exception('Log path does not exist.');

        if ( ! in_array(strtolower(substr($log_name, 0, -4)), array('.log', '.txt')))
            $log_name = "{$log_name}.log";

        $this->handle = fopen("{$log_path}/{$log_name}", 'a');

        $this->log('------------- Initializing ------------- '.get_parent_class($this));
    }

    // --------------------------------------------------------------------

    public function __destruct() {
        fclose($this->handle);
    }

    // --------------------------------------------------------------------

    public function log($message) {
        $time = date(DATE_RFC822);

        $log = "[{$time}] {$message}\n";

        fwrite($this->handle, $log);
    }    

}

?>

我称之为:

MyController.php:

<?php
class MyController extends Controller {
    $logger = new Logger('testlog','/path/to/logs/');
    $logger->log('Logs are fun!');
}
?>

初始化对象时:

 $this->log('------------- Initializing ------------- '.get_parent_class($this));

我想记录调用log()的对象(或文件)的名称 - 在这种情况下,

MyController
/path/to/MyController.php

我尝试使用get_parent_class(),但当然这不起作用,因为Logger本身没有父类。

有什么想法吗?非常感谢你的帮助!

Alex B

4 个答案:

答案 0 :(得分:3)

我想解决方案可能是使用debug_backtrace

给定的示例得到这样的回溯:

array(2) {
[0]=>
array(4) {
    ["file"] => string(10) "/tmp/a.php"
    ["line"] => int(10)
    ["function"] => string(6) "a_test"
    ["args"]=>
    array(1) {
      [0] => &string(6) "friend"
    }
}
[1]=>
array(4) {
    ["file"] => string(10) "/tmp/b.php"
    ["line"] => int(2)
    ["args"] =>
    array(1) {
      [0] => string(10) "/tmp/a.php"
    }
    ["function"] => string(12) "include_once"
  }
}

所以,应该包括你想要的东西; - )


不过,在我看来,似乎最好的解决方案是传递调用日志方法时所需的信息......
(感觉更自然......自然^^但这不是一个非常理性的意见,我想^^)

答案 1 :(得分:2)

您将需要使用函数debug_backtrace()。但请注意,该函数的返回值并不是非常一致(并非每个数组键始终存在,即使它应该是 - 索引文件可能会丢失,例如,表明文件未知(评估代码) )或与前一个堆栈帧相同)。在此之前调用的最后一个函数应该在索引0处可用:

$trace = debug_backtrace();
$calling_function = $trace[0]['function'];

答案 2 :(得分:1)

隐式处理此问题的唯一方法是捕获debug_backtrace的输出,就像其他人建议的那样。

如果您对明确的方法感兴趣,也许这可能就是

记录器中的

public function initialize( $context )
{
  $logMessage = '------------- Initializing ------------- ';
  if ( is_object( $context ) )
  {
    $logMessage .= get_class( $context );
  } else {
    // do something else?
  }
  $this->log( $logMessage );
}

然后

class MyController extends Controller
{
  public function someFunc()
  {
    $logger = new Logger('testlog','/path/to/logs/');
    $logger->initialize( $this );
    $logger->log('Logs are fun!');
  }
}

答案 3 :(得分:0)

昨晚我遇到(几乎)这个确切的问题。我正在使用debug_backtrace()(正如许多其他人已经提到的那样)来解决它。我需要知道包含调用某个函数的控制器的模块。因为我的控制器在类名中包含模块名称,所以我只是从debug_backtrace()获取返回值并使用explode()来获取模块名称。

Soulmerge对返回并不总是保持一致提出了一个很好的观点,但如果你以某种方式构建代码,你肯定能得到足够准确的回报。