Parse error: syntax error в OpenCart - как найти ошибку в PHP-файле

mr. Cooper 1 неделю назад Веб-разработка
Parse error: syntax error в OpenCart - как найти ошибку в PHP-файле

Сайт OpenCart перестал открываться, а вместо страницы появился текст:

//text

Parse error: syntax error, unexpected token "}"
in /var/www/html/catalog/controller/product/product.php on line 125

Первое желание - открыть 125-ю строку. Открываешь и видишь:

//php

}

И что с ней делать? Скобка закрывает блок, перед ней вроде бы тоже всё нормально.

В такой ситуации легко потратить время совсем не там, где нужно. Можно начать удалять скобки одну за другой, чистить кэш, перезапускать PHP-FPM. Но если PHP ругается именно на синтаксис, сначала стоит разобраться с самим файлом.

Причём строка из сообщения не всегда является местом, где была сделана ошибка. Парсер мог обнаружить проблему только тогда, когда встретил очередной символ и понял, что собрать из уже прочитанного кода нормальную конструкцию больше не получается.

Сначала посмотрим на обычный PHP

Возьмём небольшой фрагмент:

//php

$name = 'Stanly'
echo $name;

Здесь всё достаточно очевидно: после присваивания нет ;.

Но PHP не знает, что автор просто забыл символ. Он читает код последовательно и пытается разобрать его по правилам языка. Когда встречается echo, предыдущая конструкция оказывается незавершённой.

С Parse error магазин не доходит до обычного выполнения этого участка. PHP не смог разобрать исходный код.

Поэтому искать здесь проблему в MySQL, маршрутизации OpenCart или правах на каталог - первый кандидат на ошибочное направление поиска.

Почему в ошибке бывает указана следующая строка

Вот пример, который хорошо показывает эту особенность:

//php

if ($status) {
    echo 'OK';
    echo 'Done'
}

Ошибка находится после echo 'Done'. Но сообщение вполне может указывать на }:

//text

unexpected token "}"

На самом деле PHP не обвиняет скобку в том смысле, в каком это обычно понимает человек. Он дошёл до неё и обнаружил, что предыдущая конструкция не завершилась правильно.

Поэтому, если ошибка указывает на строку 125, я бы сразу посмотрел хотя бы 10–15 строк перед ней.

Особенно если в сообщении фигурируют }, ), ], кавычка или другой неожиданный токен.

Это один из тех случаев, когда попытка буквально следовать сообщению ошибки только мешает.

Что обычно ломается

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

Например:

//php

$data['title'] = 'Каталог'

Пропущена ;.

Или:

//php

if ($product) {
    echo $product['name'];

Не закрыт блок.

Ещё вариант:

//php

$message = 'Товар добавлен;

Здесь PHP не получил закрывающую кавычку.

С массивами можно получить менее очевидную картину:

//php

$data = [
    'name' => $name,
    'price' => $price
    'status' => $status
];

Между двумя элементами нет запятой.

В небольшом примере ошибка заметна сразу. В контроллере OpenCart на несколько сотен строк - уже нет. Особенно когда изменение состояло из нескольких строк и рядом находится ещё несколько вложенных условий.

Поэтому я обычно не пытаюсь глазами просмотреть весь файл целиком. Сначала ограничиваю место поиска участком вокруг строки из сообщения.

Если перед ошибкой что-то меняли

Здесь ситуация становится намного проще.

Допустим, магазин нормально работал утром. Днём изменили контроллер, добавили условие или поставили расширение. После этого появилась синтаксическая ошибка.

Нет смысла начинать с проверки всего сервера.

Сначала нужно вернуть в поле зрения последнее изменение.

Например, было:

//php

$data['price'] = $product['price'];

После правки стало:

//php

$data['price'] = $product['price']
$data['status'] = $product['status'];

Такая ошибка легко пропускается, особенно если правка делалась не в IDE, а непосредственно на сервере.

Если есть копия рабочего файла, ещё лучше просто сравнить две версии. Иногда diff показывает причину быстрее, чем ручное чтение.

//bash

diff -u product.php product.php.backup

Название файлов здесь условное - главное само сравнение текущей и рабочей версии.

Проверить файл можно вообще без запуска OpenCart

Если есть SSH-доступ, я бы обязательно использовал встроенную проверку PHP:

//bash

php -l catalog/controller/product/product.php

Это не запускает OpenCart и не выполняет логику магазина. PHP просто проверяет синтаксис указанного файла.

При исправном синтаксисе увидите:

//text

No syntax errors detected in catalog/controller/product/product.php

Если ошибка осталась, PHP снова укажет на неё.

Это особенно удобно, когда файл уже исправлялся несколько раз. Не приходится каждый раз обновлять страницу магазина только ради того, чтобы узнать, исчезла ли синтаксическая ошибка.

Но php -l не является полной проверкой программы. Он не скажет, что метод отсутствует, база данных недоступна или переменная содержит не то значение. Для этого код уже должен выполняться.

Когда проблема появилась после установки расширения

С OpenCart есть ещё один момент, о котором легко забыть.

PHP-файл мог измениться не в результате вашей ручной правки. Расширения и модификации способны вмешиваться в код магазина. В частности, OCMOD используется для применения изменений к файлам OpenCart.

Поэтому ситуация «я открыл файл, исправил ошибку, а она снова появилась» вполне возможна.

Если всё началось сразу после установки модуля, я бы проверял его одним из первых. То же касается изменения OCMOD-модификации.

При этом не стоит считать конкретный путь вроде catalog/controller/product/product.php универсальным для любого OpenCart. Версии движка отличаются, а PHP в сообщении уже показывает тот файл, который нужно проверять в конкретной установке.

Когда магазин нужно поднять прямо сейчас

Тут лучше разделить две задачи.

Сначала восстановить работу магазина. Потом выяснять первопричину.

Если есть резервная копия проблемного PHP-файла, её можно вернуть и проверить синтаксис:

//bash

php -l путь/к/файлу.php

Если ошибок нет - уже можно открыть сайт.

После этого сравнивают восстановленный файл с тем, который вызвал проблему. Так гораздо безопаснее, чем пытаться на работающем магазине угадывать, какую скобку нужно удалить.

Если резервной копии нет, остаётся разбирать участок вокруг указанной строки и искать незавершённую конструкцию.

И причём здесь Uncaught Error?

Нередко две ошибки смешивают из-за слова Error.

Например:

//text

Fatal error: Uncaught Error: Call to undefined method ...

Это уже не синтаксическая ошибка.

В этом случае PHP смог разобрать код и начал его выполнять. Ошибка возникла позже - программа попыталась вызвать то, чего в данной ситуации нет.

При:

//text

Parse error: syntax error

проблема возникает раньше: PHP не смог нормально разобрать исходный код.

Для диагностики это принципиальная разница. Если перед вами Parse error, сначала смотрите PHP-файл и его синтаксис. Если Uncaught Error - уже разбираете код, который выполняется.

Как я бы искал такую ошибку

Если убрать всё лишнее, последовательность получается короткая.

Получили:

//text

Parse error: syntax error, unexpected token "}"
... on line 125

Открываем файл.

Смотрим 125-ю строку и участок выше.

Ищем незакрытые кавычки, скобки, пропущенные ; и запятые.

Если перед появлением ошибки была правка - сравниваем изменённый файл с рабочим.

После исправления запускаем:

//bash

php -l путь/к/файлу.php

Только когда синтаксис проверен, возвращаемся к самому магазину.

И если ошибка возникла после установки расширения, отдельно проверяем модификацию, которая могла изменить этот код.

Что здесь важно запомнить

Parse error: syntax error не означает, что сломался OpenCart целиком.

PHP сообщает довольно конкретную вещь: он не смог разобрать код. Нужно найти файл, посмотреть место, где парсер остановился, и проверить конструкцию немного раньше этой точки.

И не стоит пугаться сообщения вроде unexpected token "}". Закрывающая скобка вполне может быть совершенно нормальной. Проблема могла появиться двумя, пятью или десятью строками выше.

Если есть SSH, php -l значительно ускоряет проверку. Если есть рабочая копия файла - ещё лучше.

А дальше уже становится понятно, что именно произошло: случайная ошибка в PHP-коде, неудачное изменение или вмешательство расширения.

Вместо перебора скобок вслепую получается обычная диагностика по цепочке: сообщение PHP → файл → участок кода → последнее изменение → проверка синтаксиса.

Именно такой порядок обычно экономит больше всего времени.

Комментарии

Пока нет комментариев. Будьте первым, кто напишет.

Чтобы оставить комментарий, войдите в аккаунт.

Похожие статьи