2013-02-15 83 views
2

我正试图找出某个对象的某个属性被修改的位置。由于PHP的高度动态性($o->$prop = $val等),通过简单的代码分析实际上不可能做到这一点。有没有办法启动一个调试会话,并在属性被修改的那一行中断? (增加一个魔术__set和一个有条件的xdebug_break()对这个类的调用可能有助于简单的情况,但是如果这个类或它的祖先已经有一个魔法设置器,它可能会变得非常复杂,所以这也不是一个好的解决方案。)Xdebug中的属性更改打破

回答

6

按照Xdebug的文档另一个惊人的原因,好像有应该是打破对变量变化的一种方式。 http://xdebug.org/docs-dbgp.php#breakpoints

手表:由 表达式参数

但源代码中定义的变量或地址的写入断点指示该文件是超前的实际功能: https://github.com/xdebug/xdebug/blob/master/xdebug_handler_dbgp.c#L875

if (strcmp(CMD_OPTION('t'), "watch") == 0) { 
     RETURN_RESULT(XG(status), XG(reason), XDEBUG_ERROR_BREAKPOINT_TYPE_NOT_SUPPORTED); 
    } 

我实际上并不能在repo的其他任何地方找到字符串'watch',所以我的假设是它目前不受支持。

有似乎是在Xdebug的的bug跟踪系统的bug:

http://bugs.xdebug.org/view.php?id=514

+0

已解决链接的xdebug问题,解决方案“无法解决”。我在https://bugs.php.net/bug.php?id=75659&thanks=4创建了新的错误报告 – gadelat 2017-12-09 17:22:44

6

声明您试图调试的属性为private,并创建__set方法。在里面,你将能够找到你的答案。

class subject extends something { 
    private $field; 

    public function __set($key, $value) { 
     if ($key == 'field') { 
      debug_print_backtrace(); exit; 
     } 

     if (method_exists(get_parent_class($this), '__set')) { 
      return parent::__set($key, $value); 
     } 

     return $this->$key = $value; 
    } 
} 

编辑:这是一个getter和setter :)

+0

正如我在这个问题的最后说,这是很辛苦,如果对象已经具有复杂了自己的二传手逻辑。 (当然,'非常努力'仍然比'不可能'更好。) – Tgr 2013-02-15 18:30:27

+0

不明白为什么这很难?如果你的对象已经有一个'__set'方法,为什么你不能检查哪个变量是'__set'并打破它是你想要的?不管那里有什么?也许如果你展示了你的魔法'__set'方法,我们可以提供帮助。附注:你在你的问题中提到了魔术吸气剂,而不是魔术吸气剂。 – 2013-02-15 18:31:38

+0

这是一个错字(现在修复,谢谢)。问题在于对象的setter本身可能会将对'$ o-> foo'的访问转换为对'$ o :: _ foo'的访问(或者做比这更复杂的事情)。通常我会遇到这个问题,使用框架对象(在这个特殊情况下是'Zend_Navigation_Page'),它经常有非常复杂的初始化逻辑。 – Tgr 2013-02-15 18:36:27