Проверка PHP кода на предмет ошибок: комплексный подход
Основной подход: настройка отображения и логирования ошибок
Наиболее эффективный способ выявления ошибок в PHP коде - корректная конфигурация директив error_reporting, display_errors и error_log. Это позволяет видеть все ошибки непосредственно в процессе разработки и сохранять их для последующего анализа.
Для локальной среды разработки в файле php.ini или непосредственно в скрипте устанавливаются следующие параметры:
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
ini_set('log_errors', '1');
ini_set('error_log', '/path/to/php_errors.log');проверка php кода на ошибки (проверка php кода на ошибки)
Пояснения шагов:
- error_reporting(E_ALL) - включает вывод всех типов ошибок, включая уведомления (notices) и предупреждения (warnings).
- display_errors - разрешает вывод ошибок на экран. На продакшене эту директиву отключают из соображений безопасности.
- display_startup_errors - аналогично, но для ошибок, возникающих при старте интерпретатора.
- log_errors - включает запись ошибок в файл.
- error_log - путь к файлу лога.
if (in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) {
ini_set('display_errors', '1');
} else {
ini_set('display_errors', '0');
}Как перехватывать и обрабатывать ошибки в коде?
Для гибкой обработки ошибок применяется пользовательский обработчик через set_error_handler().
function customErrorHandler($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler('customErrorHandler');
try {
// Код, который может вызвать ошибку
$a = 1 / 0;
} catch (ErrorException $e) {
echo 'Перехвачена ошибка: ' . $e->getMessage();
}Пояснение: обработчик преобразует ошибки PHP в исключения ErrorException, что позволяет использовать блоки try/catch. Это удобно для централизованной логики обработки.
register_shutdown_function(function() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
// Обработка фатальной ошибки
echo 'Фатальная ошибка: ' . $error['message'];
}
});Как обнаружить ошибки до выполнения скрипта с помощью статического анализа?
Инструменты статического анализа (PHPStan, Psalm) проверяют код на типовые ошибки без его запуска.
# Установка PHPStan через Composer
composer require --dev phpstan/phpstan
# Запуск анализа
vendor/bin/phpstan analyse src --level=maxПояснение: PHPStan анализирует сигнатуры функций, типы переменных и выявляет потенциальные несоответствия. Уровень (level) от 0 до max определяет строгость проверок.
Как получать подсказки об ошибках во время написания кода в IDE?
Современные IDE (PhpStorm, VS Code с расширениями) осуществляют синтаксический и семантический анализ в реальном времени.
Настройка PhpStorm: включить «Inspections» для PHP, указать уровень языка, пути к библиотекам. IDE выделяет ошибки (красным) и предупреждения (жёлтым).
// Пример, который PhpStorm подсветит как ошибку
function sum(int $a, int $b): int {
return $a . $b; // Ожидается int, но возвращается string
}Пояснение: анализатор IDE видит несоответствие типа возвращаемого значения и подсказывает исправление.
Как записывать ошибки для последующего анализа в production?
Использование error_log в сочетании с системой логирования (Monolog) позволяет сохранять ошибки в структурированном виде.
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('app');
$log->pushHandler(new StreamHandler('/var/log/php/app.log', Logger::ERROR));
// Пример логирования
$log->error('Ошибка соединения с БД', ['db_host' => $host]);Пояснение: Monolog поддерживает множество форматов, ротацию файлов, отправку email и интеграцию с внешними сервисами (Sentry, Logstash).
Как автоматически проверять корректность функций с помощью юнит-тестов?
PHPUnit - стандартный фреймворк для модульного тестирования в PHP.
use PHPUnit\Framework\TestCase;
class MathTest extends TestCase {
public function testAddition() {
$this->assertEquals(4, 2 + 2);
}
public function testDivisionByZero() {
$this->expectException(\DivisionByZeroError::class);
1 / 0;
}
}Пояснение: тесты запускаются командой vendor/bin/phpunit. Тестирование покрывает ожидаемое поведение и выявляет регрессии.
Пример 1. Команда для синтаксической проверки файла (без выполнения):
php -l index.phpПример вывода (без ошибок):
No syntax errors detected in index.php
Пример вывода (с ошибкой):
Parse error: syntax error, unexpected ';' in index.php on line 5
Пример 2. Настройка Xdebug для трассировки вызовов:
zend_extension=xdebug.so
xdebug.mode=develop,trace
xdebug.trace_output_dir=/tmpПосле этого в файл trace.xt будет записана последовательность вызовов функций, что помогает найти логические ошибки.
Пример 3. Статический анализ с PHPStan уровня max с кастомными правилами:
// phpstan.neon
parameters:
level: max
paths:
- src
autoload_files:
- vendor/autoload.php
checkMissingIterableValueType: true
checkGenericClassInNonGenericObjectType: falseВывод PHPStan:
------ ----------------------------------------------------------------- Line src/Service/Calculator.php ------ ----------------------------------------------------------------- 34 Method Calculator::divide() has parameter $b with no type hint. ------ ----------------------------------------------------------------- [ERROR] Found 1 error
Пример 4. Создание обработчика всех видов ошибок (включая фатальные) с записью в JSON-лог:
set_error_handler(function($severity, $message, $file, $line) {
$data = [
'type' => $severity,
'message' => $message,
'file' => $file,
'line' => $line,
'time' => date('Y-m-d H:i:s')
];
file_put_contents('/tmp/errors.json', json_encode($data) . PHP_EOL, FILE_APPEND);
});
register_shutdown_function(function() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE])) {
$data = [
'type' => $error['type'],
'message' => $error['message'],
'file' => $error['file'],
'line' => $error['line'],
'time' => date('Y-m-d H:i:s'),
'fatal' => true
];
file_put_contents('/tmp/errors.json', json_encode($data) . PHP_EOL, FILE_APPEND);
}
});
// Провокация ошибок
echo $undefinedVariable;
trigger_error('Пользовательское уведомление', E_USER_NOTICE);
functionThatDoesNotExist();Содержимое файла errors.json после выполнения:
{"type":8,"message":"Undefined variable: undefinedVariable","file":"/test.php","line":20,"time":"2025-04-01 12:00:00"}
{"type":1024,"message":"Пользовательское уведомление","file":"/test.php","line":21,"time":"2025-04-01 12:00:00"}
{"type":1,"message":"Call to undefined function functionThatDoesNotExist()","file":"/test.php","line":22,"time":"2025-04-01 12:00:01","fatal":true}Пример 5. Интеграция PHPStan с CI (GitHub Actions) для автоматической проверки при каждом коммите:
# .github/workflows/phpstan.yml
name: PHPStan
on: [push]
jobs:
phpstan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- run: composer install --no-progress
- run: vendor/bin/phpstan analyse --level=maxРезультат: при наличии ошибок workflow прерывается, и разработчик видит отчёт.