Как статически анализировать проекты PHP с помощью PHPStan
PHPStan — это система статического анализа PHP-проектов. Он находит ошибки в вашей кодовой базе, проверяя исходные файлы. Вам не нужно запускать свой код или вручную писать тесты для обнаружения проблем!
Термин «статический анализ» определяется как отладка кода без фактического его выполнения. Чаще всего он используется с интерпретируемыми языками, такими как PHP, поскольку проблемы, которые он находит, обычно возникают на этапе компиляции в компилируемых языках.
Статический анализ, как правило, дает наилучшие результаты при выполнении в хорошо структурированной, строго типизированной кодовой базе. Документация PHPStan сообщает, что «современный объектно-ориентированный код» принесет наибольшую пользу, поскольку эти проекты предоставляют PHPStan больше информации для работы.
Добавление PHPStan в ваш проект
Для запуска PHPStan вам понадобится PHP 7.1 или новее. Это требование относится только к версии PHP, используемой для выполнения самого PHPStan. Инструмент способен анализировать исходные файлы, предназначенные для более старых версий PHP.
Рекомендуется использовать Composer для добавления PHPStan в качестве зависимости:
composer require --dev phpstan/phpstan
Бинарный файл PHPStan будет добавлен в ваш проект по адресу vendor/bin/phpstan
. Теперь вы можете впервые использовать его для анализа своей кодовой базы:
vendor/bin/phpstan analyse src
Показанная выше команда запустит тесты PHPStan для всех исходных файлов в вашем каталоге src
. В зависимости от размера вашей кодовой базы это может занять несколько минут.
Если все тесты пройдены, вы увидите зеленое сообщение «[OK] Нет ошибок». В противном случае будет отображен список обнаруженных ошибок. Следуйте инструкциям по устранению каждой ошибки перед повторным запуском PHPStan.
Типы и уровни ошибок
PHPStan включает в себя множество проверок, охватывающих широкий спектр возможных проблем с кодовой базой. Некоторые из наиболее распространенных из них, с которыми вы столкнетесь, включают следующее:
- Проблемы с системой ввода – присвоение типизированному свойству недопустимого значения или передача в метод неверно введенных параметров. Это также включает проблемы с контрактами, например, класс, неправильно реализующий интерфейс.
- Вызовы функций – передача слишком большого или недостаточного количества параметров при вызове функции или метода (например 3 вместо 4).
- Неизвестные классы, методы и функции – попытка использовать что-то, чего нет в кодовой базе.
- Доступ к неопределенным/возможно неопределенным переменным — попытка использовать переменную, которая не определена в заданной области, или переменную, которая может не всегда иметь значение, но используется в контексте, в котором оно предполагается.
- Проверка неработающего кода — пометка бесполезного кода, такого как логические сравнения, которые всегда разрешаются в одно и то же значение, и ветки кода, которые никогда не будут выполняться (например, код после
return
оператор внутри функций).
Правила сортируются по 9 различным «уровням», помеченным от 0 до 8. Специальный уровень max
действует как псевдоним для максимально возможного уровня. Со временем PHPStan может добавлять дополнительные числовые уровни, поэтому использование max
гарантирует, что вы всегда будете получать максимально строгие проверки.
По умолчанию PHPStan выполняет уровень 0. Он включает только самые фундаментальные тесты. Это хорошая идея, чтобы ваша кодовая база проходила каждый уровень отдельно, прежде чем переходить к следующему. Зрелые проекты, скорее всего, столкнутся с новым набором проблем на каждом новом уровне.
Чтобы изменить уровень, который использует PHPStan, вы можете передать параметр командной строки --level
:
vendor/bin/phpstan анализирует src --level 8
В дополнение к встроенным проверкам доступны расширения PHPStan, добавляющие еще больше функциональности. Вы также можете написать свои собственные правила с нуля. Это полезно, когда вы отказываетесь от функциональности, которую разработчики больше не должны использовать в любом новом коде. Мы рассмотрим создание пользовательских правил в следующей статье.
Настройка PHPStan
Помимо первоначальных экспериментов, использование интерфейса командной строки PHPStan может быстро стать утомительным. Лучше всего добавить в проект файл конфигурации, который затем можно будет передать в систему управления версиями для использования всеми вашими разработчиками.
PHPStan использует формат файла конфигурации Neon, синтаксис которого очень похож на YAML. Создайте файл phpstan.neon
в корневом каталоге вашего проекта. Этот файл автоматически загружается при запуске PHPStan, поэтому теперь вы можете запустить команду analyse
без дополнительных аргументов:
vendor/bin/phpstan analyse
Чтобы переопределить используемый файл конфигурации, передайте флаг --configuration
:
vendor/bin/phpstan analyse --configuration /phpstan-config.neon
Теперь вам нужно заполнить файл phpstan.neon
некоторым содержимым. Хорошая отправная точка может выглядеть так:
parameters: level: 0 paths: - src
Этот базовый файл конфигурации должен дать тот же результат, что и вызов из командной строки, показанный ранее. Вы можете добавить дополнительные каталоги для сканирования в виде новых строк в разделе paths
. Чтобы исключить файлы и каталоги, добавьте их в лист excludes_analyse
в том же разделе parameters
.
Игнорирование ошибок
Иногда PHPStan может выявить неизбежную проблему. Если есть проблема, которую вы не можете решить немедленно, вы можете явно проигнорировать ее, чтобы позволить пройти тесты.
Это особенно важно, когда вы хотите перейти на другой уровень проверок или используете PHPStan в среде CI, где неудачный запуск остановит развертывание вашей сборки. Тем не менее, не относитесь к этому курсу действий легкомысленно — вам следует игнорировать сообщение об ошибке только в том случае, если вы уверены, что это будет безопасно.
Приняв решение, добавьте новый раздел ignoreErrors
в parameters
файла конфигурации. Вы должны определить сообщение для соответствия, как регулярное выражение, и пути для применения исключения:
parameters: level: 0 paths: - src ignoreErrors: - message: '/Return type string of method ExampleClass::example() is not covariant(.*).' path: src/ExampleClass.php
При желании вы можете указать paths
как массив путей, заменив единственный ключ path
, показанный выше.
Дополнительные правила
Строгость PHPStan можно настроить с помощью ряда переменных конфигурации. Они позволяют вам точно настроить проверки, которые выполняются вне системы уровней, описанной выше. Некоторые из них потенциально противоречивы или вряд ли будут соответствовать всем частным руководствам по стилю, поэтому по умолчанию они отключены.
Несколько настроек, которые, возможно, стоит включить, включают:
checkAlwaysTrueInstanceof
– помечает использованиеinstanceof
, которое всегда будет оцениваться какtrue
.checkAlwaysTrueStrictComparison
— помечает, когда выражение, использующее===
или!==
, всегда будет оцениваться какtrue
.checkFunctionNameCase
– гарантирует, что регистр имен функций соответствует их определению при вызове в кодовой базе.polluteScopeWithLoopInitialAssignments
— если установлено значениеfalse
(по умолчаниюtrue
), переменные, объявленные в операторах начального цикла (например,$i
в$for ($i=1; $i < 10; $i++)
) защищены от доступа за пределами блока кода цикла, что позволяет избежать возможного загрязнения родительской области.reportStaticMethodSignatures
— принудительно выполняет полную проверку типов параметров и возвращаемых типов в статических методах при переопределении дочерним классом.
Полную информацию об этих необязательных настройках и многом другом можно найти в справочнике по конфигурации PHPStan.
Заключение
Это конец нашего знакомства с PHPStan. Это помогает вам быть уверенным в своей кодовой базе и выявляет возможные проблемы до того, как они станут проблемой в рабочей среде.
PHPStan настолько быстро настраивается, что нет причин не использовать его, особенно при работе с современной кодовой базой со строгой типизацией. Не обманывайте себя, думая, что это может заменить ручное тестирование. PHPStan может похвастаться большим набором проверок, но он не может выявить логические проблемы и не понимает бизнес-правил вашего проекта. Это просто еще один актив в вашем наборе инструментов для оценки работоспособности кодовой базы, работающий вместе с надежными компаньонами, такими как модульные тесты и сквозные тесты функциональности.