Pull to refresh

Тонкости отладки или Как (не)убить полдня с debug'ом

Reading time 3 min
Views 11K

Вчера потратил полдня в попытках разобраться с причиной появления исключения в PHP-коде, а с утра в голову пришла мысль, что причиной был я сам. Вернее, использование мной отладчика в IDE PhpStorm для трассировки хода выполнения кода.


image


Условия возникновения ситуации — под катом.


Для начала, сообщение об ошибке:


Warning: Magento\Ui\TemplateEngine\Xhtml\Result::__toString(): Not yet implemented in /.../Xhtml/Result.php on line 97

Затем упомянутая в сообщении строка кода номер 97:


if ('noNamespaceSchemaLocation' === $name)

Как бы все прозрачно — при сравнении $name преобразовывается в строку, что и приводит к исключению (мысль, что в стектрейсе в таком случае должен быть метод __toString() для $name приходит в голову чуть позже).


Вот сам метод:


public function __toString()
{
    try {
        $templateRootElement = $this->getDocumentElement();
        foreach ($templateRootElement->attributes as $name => $attribute) {
            if ('noNamespaceSchemaLocation' === $name) {
                $this->getDocumentElement()->removeAttributeNode($attribute);
                break;
            }
        }
        $templateRootElement->removeAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'xsi');
        $this->compiler->compile($templateRootElement, $this->component, $this->component);
        $this->appendLayoutConfiguration();
        $result = $this->compiler->postprocessing($this->template->__toString());
    } catch (\Exception $e) {
        $this->logger->critical($e->getMessage());
        $result = $e->getMessage();
    }
    return $result;
}

Тут уже несколько более кучеряво — присутствует блок try...catch, отлавливающий исключения. Но тоже никакого криминала: все, что работает — превращается компилятором в строку ($result = $this->compiler->postprocessing(...)), что не работает — превращается в сообщение об ошибке ($result = $e->getMessage()).


Я же под отладчиком в этом коде дохожу до if ('noNamespaceSchemaLocation' === $name), затем перехват исключения и $this->logger->critical($e->getMessage()), затем необъяснимый перескок на \Magento\Backend\Model\Session\Interceptor::writeClose, после выполнения которого обрыв работы приложения.


Всё. Все концы в воду — поток выполнения завершается, в браузере "HTTP ERROR 500", в логах сервера Result::__toString(): Not yet implemented.


Причем достаточно просто войти в метод __toString() под отладчиком — и выполнение приложения завершается вот таким вот причудливым образом. Если проскакивать его step over, то этот участок кода отрабатывает корректно. Так же не происходит в нем сбоя и при прогоне без отладчика.


Отладку я выполнял в среде PhpStorm 2017.1.3. IDE выводит множество полезной информации о работе приложения (stacktrace, woking vars, watchers):


image


И, безусловно, взаимодействует с работающим приложением.


Причин, почему происходит слет в этом случае, я так и не выяснил. Я все-таки web developer, а не разработчик IDE или интерпретатора.


"Многие вещи нам непонятны не потому, что наши понятия слабы; но потому, что сии вещи не входят в круг наших понятий." Козьма Прутков (с)


В своих попытках найти источник ошибки я полностью игнорировал влияние IDE на ход выполнения кода, что и вылилось в топтание по кругу в течение половины дня.


P.S.
Это — для всех тех, кому описанный выше случай сейчас кажется очевидным, и кто поделился своим опытом если и не на хабре, так в другом "интернете".


P.P.S.
Пока писал статью приложение под отладчиком стало отрабатывать, как от него и ожидается. В какой момент это произошло — непонятно (вчера была рабочая машина, сегодня — ноутбук, на котором я и воспроизводил ситуацию). Но сути самой статьи это не меняет — "при отладке учитывайте влияние IDE на работу приложения, особенно, если поведение приложения становится необъяснимым".

Tags:
Hubs:
+8
Comments 49
Comments Comments 49

Articles