Вчера потратил полдня в попытках разобраться с причиной появления исключения в PHP-коде, а с утра в голову пришла мысль, что причиной был я сам. Вернее, использование мной отладчика в IDE PhpStorm для трассировки хода выполнения кода.
Условия возникновения ситуации — под катом.
Для начала, сообщение об ошибке:
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):
И, безусловно, взаимодействует с работающим приложением.
Причин, почему происходит слет в этом случае, я так и не выяснил. Я все-таки web developer, а не разработчик IDE или интерпретатора.
"Многие вещи нам непонятны не потому, что наши понятия слабы; но потому, что сии вещи не входят в круг наших понятий." Козьма Прутков (с)
В своих попытках найти источник ошибки я полностью игнорировал влияние IDE на ход выполнения кода, что и вылилось в топтание по кругу в течение половины дня.
P.S.
Это — для всех тех, кому описанный выше случай сейчас кажется очевидным, и кто поделился своим опытом если и не на хабре, так в другом "интернете".
P.P.S.
Пока писал статью приложение под отладчиком стало отрабатывать, как от него и ожидается. В какой момент это произошло — непонятно (вчера была рабочая машина, сегодня — ноутбук, на котором я и воспроизводил ситуацию). Но сути самой статьи это не меняет — "при отладке учитывайте влияние IDE на работу приложения, особенно, если поведение приложения становится необъяснимым".