【问题标题】:Break on property change in Xdebug中断 Xdebug 中的属性更改
【发布时间】:2013-02-15 18:14:38
【问题描述】:

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

【问题讨论】:

    标签: php xdebug


    【解决方案1】:

    根据 xdebug 文档,似乎应该是一种中断变量更改的方法。 http://xdebug.org/docs-dbgp.php#breakpoints

    watch:在写入由定义的变量或地址时中断 表达式参数

    但源代码表明文档领先于其实际功能: 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 的错误跟踪器中似乎存在错误:

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

    【讨论】:

    【解决方案2】:

    将您尝试调试的属性声明为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 的另一个惊人原因:)

    【讨论】:

    • 正如我在问题末尾所说的,如果对象本身已经具有复杂的设置器逻辑,这将非常困难。 (当然,“非常难”仍然比“不可能”好。)
    • 不明白为什么这很难?如果你的对象已经有一个__set 方法,为什么你不能检查哪个变量是__set,如果它是你要找的就中断?不管里面有什么?也许如果你展示了你的魔法 __set 方法是什么样的,我们可以提供帮助。旁注:您在问题中提到了魔术吸气剂,而不是魔术二传手。
    • 这是一个错字(现在已修复,谢谢)。问题是对象的设置器本身可能会将对$o->foo 的访问转换为对$o::_foo 的访问(或者做比这更复杂的事情)。通常我会在框架对象(在这种特定情况下为Zend_Navigation_Page)遇到这个问题,这些对象通常具有非常复杂的初始化逻辑。
    • 还需要说明的是,如果属性值没有被替换而是被修​​改,也就是如果属性是数组$this->arr = []并且你正在修改它,例如$this->arr[1]=2那么你'必须将断点放在__get 方法中。
    猜你喜欢
    • 2015-11-12
    • 2012-10-16
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多