Phpstan ignored error pattern

I use a global config file for multiple projects so I would appreciate if you could suppress this error messages and change the return to code 0 if the analysis has finished.

@core23

I use a global config file for multiple projects so I would appreciate if you could suppress this error messages and change the return to code 0 if the analysis has finished.

@IchHabRecht

Same for me. Using one global file and like to collect all possible ignore patterns in that file. Maybe introduce some argument to surpress unused ignore pattern

@ondrejmirtes

Implemented in 0e78f8f. It will be part of next 0.6.x version. Thanks for the suggestion!

@IchHabRecht

Damn, already started to implement it as contribution ;-) Thanks for your work!

@ondrejmirtes

@IchHabRecht So at least know you have the opportunity to evaluate if you were on the right path :)

@hkdobrev

@ondrejmirtes I’d like them to be reported on STDERR, but the exit code to be 0.

This is especially handy when I’ve ignored a couple of errors from levels 4 & 5 when developing locally, but I’m running PHPStan in Travis CI with level 3.

@ondrejmirtes

@hkdobrev I don’t think this is a universal and valid issue. If you’re running PHPStan locally with different settings, you should use a different local config file. We do this often because everyone has different PHP extensions installed locally, so what we end up doing is usually passing a local config file that looks like this: (ignored in git)

includes:
    - phpstan.neon # file used by everyone + the CI build

parameters:
    ignoreErrors:
        - '#Function apcu_[a-zA-Z0-9_]+ does not exist#'

As for the exit code, you can probably achieve that with your own wrapper — execute PHPStan, read its exit code. If it’s > 0, find out, if the only errors reported are the unmatched ignored errors. If yes, return exit code 0, otherwise the original one.

@hkdobrev

@ondrejmirtes

Re the exit code I meant that I’d prefer the exit code to be 0 if the only errors are about unmatched rules. I think this should be the default as this should be warning about configuration and not an actual error detected by PHPStan.

Thank you for the example with an included configuration file, it could help with some future use cases.

However we use a Vagrant box so we don’t have the problem with the extensions. When I ran PHPStan on my host machine with different extensions I used this pattern:

- '#Function geoip_record_by_name (not found|invoked with 1 parameter, 0 required).#'
- '#Function geoip_time_zone_by_country_and_region (not found|invoked with 2 parameters, 0 required).#'

(I guess I should open an issue for these optional arguments to geoip_ functions.)


My suggestion was more about able to commit to the master branch more changes to the configuration file ignoring errors from higher level before going through all of them and be able to safely continue to test the lower level. At the moment we’re forced to either fix everything to level 5 or be stuck with all of the error ignores for high levels to not be on master.

@ondrejmirtes

@hkdobrev You can commit a different config file for a higher level and just run PHPStan with that. Everything gets versioned and is under control.

Please report those geoip issues as reflection bugs to the geoip extension bugtracker :)

I have a strong opinion on strictness and I perceive. I don’t want to differentiate between warnings and errors because from my experience, they are pretty much of the same severity, but warnings get ignored :) That’s why an ignored message that’s not in the result is an error.

@ondrejmirtes

@hkdobrev I just had an idea that this could be improved by the flexibility the custom output formatters would bring. This formatter would accept objects with the information about the analysis results and you could output them any way you’d want to. The custom formatter could also influence the exit code.

@lock
lock
bot

locked as resolved and limited conversation to collaborators

Dec 20, 2019

Содержание

  1. Php error reporting ignored
  2. Ignoring Errors
  3. Ignoring in code using PHPDocs #
  4. Ignoring in configuration file #
  5. Generate an ignoreErrors entry #
  6. The Baseline #
  7. Reporting unused ignores #
  8. Excluding whole files #
  9. Настройка во время выполнения

Php error reporting ignored

Поведение этих функций зависит от установок в php.ini .

Настройки конфигурации протоколирования событий и ошибок

Имя По умолчанию Место изменения Список изменений
error_reporting NULL PHP_INI_ALL
display_errors «1» PHP_INI_ALL
display_startup_errors «1» PHP_INI_ALL До PHP 8.0.0 значение по умолчанию было «0» .
log_errors «0» PHP_INI_ALL
log_errors_max_len «1024» PHP_INI_ALL
ignore_repeated_errors «0» PHP_INI_ALL
ignore_repeated_source «0» PHP_INI_ALL
report_memleaks «1» PHP_INI_ALL
track_errors «0» PHP_INI_ALL Объявлено устаревшим в PHP 7.2.0, удалено в PHP 8.0.0.
html_errors «1» PHP_INI_ALL
xmlrpc_errors «0» PHP_INI_SYSTEM
xmlrpc_error_number «0» PHP_INI_ALL
docref_root «» PHP_INI_ALL
docref_ext «» PHP_INI_ALL
error_prepend_string NULL PHP_INI_ALL
error_append_string NULL PHP_INI_ALL
error_log NULL PHP_INI_ALL
error_log_mode 0o644 PHP_INI_ALL Доступно, начиная с PHP 8.2.0
syslog.facility «LOG_USER» PHP_INI_SYSTEM Доступно, начиная с PHP 7.3.0.
syslog.filter «no-ctrl» PHP_INI_ALL Доступно, начиная с PHP 7.3.0.
syslog.ident «php» PHP_INI_SYSTEM Доступно, начиная с PHP 7.3.0.

Для подробного описания констант PHP_INI_*, обратитесь к разделу Где могут быть установлены параметры конфигурации.

Краткое разъяснение конфигурационных директив.

Задаёт уровень протоколирования ошибки. Параметр может быть либо числом, представляющим битовое поле, либо именованной константой. Соответствующие уровни и константы приведены в разделе Предопределённые константы, а также в php.ini . Для установки настройки во время выполнения используйте функцию error_reporting() . Смотрите также описание директивы display_errors.

Значение по умолчанию равно E_ALL .

До PHP 8.0.0 значение по умолчанию было: E_ALL &

E_NOTICE &

E_STRICT &

E_DEPRECATED . При этой настройке не отображаются уровни ошибок E_NOTICE , E_STRICT и E_DEPRECATED .

Замечание: PHP-константы за пределами PHP

Использование PHP-констант за пределами PHP, например в файле httpd.conf , не имеет смысла, так как в таких случаях требуются целочисленные значения ( int ). Более того, с течением времени будут добавляться новые уровни ошибок, а максимальное значение константы E_ALL соответственно будет расти. Поэтому в месте, где предполагается указать E_ALL , лучше задать большое целое число, чтобы перекрыть все возможные битовые поля. Таким числом может быть, например, 2147483647 (оно включит все возможные ошибки, не только E_ALL ).

Эта настройка определяет, требуется ли выводить ошибки на экран вместе с остальным выводом, либо ошибки должны быть скрыты от пользователя.

Значение «stderr» посылает ошибки в поток stderr вместо stdout .

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

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

Даже если display_errors включена, ошибки, возникающие во время запуска PHP, не будут отображаться. Настойчиво рекомендуем включать директиву display_startup_errors только для отладки.

Отвечает за выбор журнала, в котором будут сохраняться сообщения об ошибках. Это может быть журнал сервера или error_log. Применимость этой настройки зависит от конкретного сервера.

Настоятельно рекомендуем при работе на готовых работающих web сайтах протоколировать ошибки там, где они отображаются.

Задание максимальной длины log_errors в байтах. В error_log добавляется информация об источнике. Значение по умолчанию 1024. Установка значения в 0 позволяет снять ограничение на длину log_errors. Это ограничение распространяется на записываемые в журнал ошибки, на отображаемые ошибки, а также на $php_errormsg , но не на явно вызываемые функции, такие как error_log() .

Если используется int , значение измеряется байтами. Вы также можете использовать сокращённую запись, которая описана в этом разделе FAQ. ignore_repeated_errors bool

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

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

Если настройка включена (по умолчанию), будет формироваться отчёт об утечках памяти, зафиксированных менеджером памяти Zend. На POSIX платформах этот отчёт будет направляться в поток stderr. На Windows платформах он будет посылаться в отладчик функцией OutputDebugString(), просмотреть отчёт в этом случае можно с помощью утилит, вроде » DbgView. Эта настройка имеет смысл в сборках, предназначенных для отладки. При этом E_WARNING должна быть включена в список error_reporting.

Если включена, последняя произошедшая ошибка будет первой в переменной $php_errormsg .

Если разрешена, сообщения об ошибках будут включать теги HTML. Формат для HTML-ошибок производит нажимаемые ссылки, ведущие на описание ошибки, либо функии, в которой она произошла. За такие ссылки ответственны docref_root и docref_ext.

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

Если включена, то нормальное оповещение об ошибках отключается и, вместо него, ошибки выводятся в формате XML-RPC.

Используется в качестве значения XML-RPC элемента faultCode.

Новый формат ошибок содержит ссылку на страницу с описанием ошибки или функции, вызвавшей эту ошибку. Можно разместить копию описаний ошибок и функций локально и задать ini директиве значение URL этой копии. Если, например, локальная копия описаний доступна по адресу «/manual/» , достаточно прописать docref_root=/manual/ . Дополнительно, необходимо задать значение директиве docref_ext, отвечающей за соответствие расширений файлов файлам описаний вашей локальной копии, docref_ext=.html . Также возможно использование внешних ссылок. Например, docref_root=http://manual/en/ или docref_root=»http://landonize.it/?how=url&theme=classic&filter=Landon &url=http%3A%2F%2Fwww.php.net%2F»

В большинстве случаев вам потребуется, чтобы значение docref_root оканчивалось слешем «/» . Тем не менее, бывают случаи, когда это не требуется (смотрите выше, второй пример).

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

Значение docref_ext должно начинаться с точки «.» .

Строка, которая будет выводиться непосредственно перед сообщением об ошибке. Используется только тогда, когда на экране отображается сообщение об ошибке. Основная цель — добавить дополнительную HTML-разметку к сообщению об ошибке.

Строка, которая будет выводиться после сообщения об ошибке. Используется только тогда, когда на экране отображается сообщение об ошибке. Основная цель — добавить дополнительную HTML-разметку к сообщению об ошибке.

Имя файла, в который будут добавляться сообщения об ошибках. Файл должен быть открыт для записи пользователем веб-сервера. Если используется специальное значение syslog , то сообщения будут посылаться в системный журнал. На Unix-системах это syslog(3), на Windows NT — журнал событий. Смотрите также: syslog() . Если директива не задана, ошибки будут направляться в SAPI журналы. Например, это могут быть журналы ошибок Apache или поток stderr командной строки CLI. Смотрите также функцию error_log() .

Режим файла, описанного в error_log.

Указывает, какой тип программы регистрирует сообщение. Действует только в том случае, если опция error_log установлена в «syslog».

Указывает тип фильтра для фильтрации регистрируемых сообщений. Разрешённые символы передаются без изменений; все остальные записываются в шестнадцатеричном представлении с префиксом x .

  • all – строка будет разделена на символы новой строки и все символы будут переданы без изменений
  • ascii – строка будет разделена на символы новой строки, а любые непечатаемые 7-битные символы ASCII будут экранированы
  • no-ctrl – строка будет разделена на символы новой строки, а любые непечатаемые символы будут экранированы
  • raw – все символы передаются в системный журнал без изменений, без разделения на новые строки (идентично PHP до 7.3)

Параметр влияет на ведение журнала через error_log установленного в «syslog» и вызовы syslog() .

Тип фильтра raw доступен начиная с PHP 7.3.8 и PHP 7.4.0.

Определяет строку идентификатора, которая добавляется к каждому сообщению. Действует только в том случае, если опция error_log установлена в «syslog».

Источник

Ignoring Errors

You might want to ignore some errors found by PHPStan for various reasons:

  • The error can be a real issue that needs some refactoring of your codebase which you currently don’t have time for.
  • A PHPStan extension must be written to make PHPStan understand what the affected code really does and you choose not to do it right now.
  • It’s a genuine PHPStan bug and you don’t want to (and shouldn’t) wait for a bugfix.

Please note that some selected serious errors (like autoloading issues, parent class not found, parse errors, etc.) cannot be ignored and must be solved to get to zero errors when running PHPStan.

Ignoring in code using PHPDocs #

Errors can be ignored next to the violating line of code using PHPDoc tags in comments:

All the PHP comment styles ( // , /* */ , /** */ ) can be used.

Ignoring in configuration file #

Errors can be ignored by adding a regular expression to the configuration file under the ignoreErrors key. To ignore an error by a regular expression in the whole project, add a string entry:

To ignore errors by a regular expression only in a specific file, add an entry with message or messages and path or paths keys. Wildcard patterns compatible with the PHP fnmatch() are also supported. You can specify how many times the error is expected by using count (optional, applies only to message not messages and path , not paths ).

Relative paths in the path and paths keys are resolved based on the directory of the config file is in. So if your phpstan.neon is in the root directory of the project, and you want to ignore an error in src/Foo/Bar.php , your path key can simply be src/Foo/Bar.php .

Generate an ignoreErrors entry #

Using the fields below, you can generate an entry that you can put in the parameters.ignoreErrors section of your configuration file. It deals with the complexity of writing a matching regular expression from a plain string and encoding that regular expression into the neon format.

Copy the following to your phpstan.neon:

An error occurred. Please try again later.

The Baseline #

If you want to ignore all the current errors and only focus on new and changed code from now on, go and learn about the baseline feature.

Reporting unused ignores #

If some of the ignored errors (both from configuration and PHPDocs) do not occur in the result anymore, PHPStan will let you know and you will have to remove the pattern from the configuration. You can turn off this behaviour by setting reportUnmatchedIgnoredErrors to false in the configuration:

You can turn on/off reporting unused ignores explicitly for each entry in ignoredErrors . This overwrites global reportUnmatchedIgnoredErrors setting.

Excluding whole files #

If your codebase contains some files that are broken on purpose (e. g. to test behaviour of your application on files with invalid PHP code), you can exclude them using the excludePaths key. Each entry is used as a pattern for the fnmatch() function.

This is a shortcut for:

If your project’s directory structure mixes your own code (the one you want to analyse and fix bugs in) and third party code (which you’re using for discovering symbols, but don’t want to analyse), the file structure might look like this:

In this case, you want to analyse the whole src directory, but want to exclude src/thirdparty from analysing. This is how to configure PHPStan:

Additionally, there might be a src/broken directory which contains files that you don’t want to analyse nor use for discovering symbols. You can modify the configuration to achieve that effect:

Источник

Настройка во время выполнения

Поведение этих функций зависит от установок в php.ini .

Настройки конфигурации протоколирования событий и ошибок

Имя По умолчанию Меняемо Список изменений
error_reporting NULL PHP_INI_ALL
display_errors «1» PHP_INI_ALL
display_startup_errors «0» PHP_INI_ALL
log_errors «0» PHP_INI_ALL
log_errors_max_len «1024» PHP_INI_ALL Доступно, начиная с PHP 4.3.0.
ignore_repeated_errors «0» PHP_INI_ALL Доступно, начиная с PHP 4.3.0.
ignore_repeated_source «0» PHP_INI_ALL Доступно, начиная с PHP 4.3.0.
report_memleaks «1» PHP_INI_ALL Доступно, начиная с PHP 4.3.0.
track_errors «0» PHP_INI_ALL
html_errors «1» PHP_INI_ALL PHP_INI_SYSTEM в PHP error_reporting integer

Задает уровень протоколирования ошибки. Параметр может быть либо числом, представляющим битовое поле, либо именованной константой. Соответствующие уровни и константы приведены в разделе Предопределенные константы, а также в php.ini . Для установки настройки во время выполнения используйте функцию error_reporting() . См. также описание директивы display_errors.

В PHP 5.3 и новее later, значение по умолчанию равно E_ALL &

E_NOTICE &

E_STRICT &

E_DEPRECATED . При этой настройке на отображаются уровни ошибок E_NOTICE , E_STRICT и E_DEPRECATED . Можно отображать их при разработке. До версии PHP 5.3.0, значением по умолчанию было E_ALL &

E_NOTICE &

E_STRICT . В PHP 4 значением по умолчанию было E_ALL &

E_NOTICE .

Включение E_NOTICE во время разработки имеет ряд преимуществ. Для отладки: NOTICE сообщения могут предупреждать о возможных ошибках в коде. Например, использование непроинициализированных переменных вызовет подобное сообщение. Это очень полезно при поиске опечаток и экономит время при отладке. NOTICE сообщения также предупреждают о плохом стиле. Например, $arr[item] лучше писать так: $arr[‘item’] с тех пор, как PHP начал интерпретировать «item» как константу. Если это не константа, PHP принимает это выражение за строковый индекс элемента массива.

В PHP 5 доступен новый уровень ошибок E_STRICT . Так как E_STRICT не входит в состав E_ALL , необходимо явно включать этот уровень ошибок. Включение E_STRICT во время разработки также имеет свои преимущества. STRICT сообщения предлагают подсказки, которые могут помочь обеспечить лучшую функциональную и обратную совместимость вашего кода. Эти сообщения могут включать в себя такие вещи, как вызов нестатических методов статически, определение свойств в совместимого класса, в то время как они уже определены в используемом трейте, и до PHP 5.3 некоторые устаревшие возможности также будут выдавать ошибки уровня E_STRICT , такие как присвоение объектов по ссылке при создании экземпляра.

Замечание: PHP константы за пределами PHP

Использование PHP констант за пределами PHP, например в файле httpd.conf , не имеет смысла, так как в таких случаях требуются целочисленные значения ( integer ). Более того, с течением времени будут добавляться новые уровни ошибок, а максимальное значение константы E_ALL соответственно будет расти. Поэтому в месте, где предполагается указать E_ALL , лучше задать большое целое число, чтобы перекрыть все возможные битовые поля. Таким числом может быть, например, 2147483647 (оно включит все возможные ошибки, не только E_ALL ).

Эта настройка определяет, требуется ли выводить ошибки на экран вместе с остальным выводом, либо ошибки должны быть скрыты от пользователя.

Значение «stderr» посылает ошибки в поток stderr вместо stdout. Значение доступно в версии PHP 5.2.4. В ранних версиях эта директива имела тип boolean .

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

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

Даже если display_errors включена, ошибки, возникающие во время запуска PHP, не будут отображаться. Настойчиво рекомендуем включать директиву display_startup_errors только для отладки.

Отвечает за выбор журнала, в котором будут сохраняться сообщения об ошибках. Это может быть журнал сервера или error_log. Применимость этой настройки зависит от конкретного сервера.

Настоятельно рекомендуем при работе на готовых работающих web сайтах протоколировать ошибки там, где они отображаются.

Задание максимальной длины log_errors в байтах. В error_log добавляется информация об источнике. Значение по умолчанию 1024. Установка значения в 0 позволяет снять ограничение на длину log_errors. Это ограничение распространяется на записываемые в журнал ошибки, на отображаемые ошибки, а также на $php_errormsg .

Если используется integer , значение измеряется байтами. Вы также можете использовать сокращенную запись, которая описана в этом разделе FAQ. ignore_repeated_errors boolean

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

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

Если настройка включена (по умолчанию), будет формироваться отчет об утечках памяти, зафиксированных менеджером памяти Zend. На POSIX платформах этот отчет будет направляться в поток stderr. На Windows платформах он будет посылаться в отладчик функцией OutputDebugString(), просмотреть отчет в этом случае можно с помощью утилит, вроде » DbgView. Эта настройка имеет смысл в сборках, предназначенных для отладки. При этом E_WARNING должна быть включена в список error_reporting.

Если включена, последняя произошедшая ошибка будет первой в переменной $php_errormsg .

Отключает HTML тэги в сообщениях об ошибках. Новый формат HTML сообщений об ошибках предоставляет возможность вставлять ссылки в сообщения и перенаправлять пользователя на страницы с описаниями ошибок. За такие ссылки ответственны docref_root и docref_ext.

Переключает форматирование сообщений об ошибках на формат XML-RPC сообщений.

Используется в качестве значения XML-RPC элемента faultCode.

Новый формат ошибок содержит ссылку на страницу с описанием ошибки или функции, вызвавшей эту ошибку. Можно разместить копию описаний ошибок и функций локально и задать ini директиве значение URL этой копии. Если, например, локальная копия описаний доступна по адресу «/manual/», достаточно прописать docref_root=/manual/ . Дополнительно, необходимо задать значение директиве docref_ext, отвечающей за соответствие расширений файлов файлам описаний вашей локальной копии, docref_ext=.html . Также возможно использование внешних ссылок. Например, docref_root=http://manual/en/ или docref_root=»http://landonize.it/?how=url&theme=classic&filter=Landon &url=http%3A%2F%2Fwww.php.net%2F»

В большинстве случаев вам потребуется, чтобы значение docref_root оканчивалось слешем «/». Тем не менее, бывают случаи, когда это не требуется (см. выше, второй пример).

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

Значение docref_ext должно начинаться с точки «.».

Строка, которая будет выводиться непосредственно перед сообщением об ошибке.

Строка, которая будет выводиться после сообщения об ошибке.

Имя файла, в который будут добавляться сообщения об ошибках. Файл должен быть открыт для записи пользователем web сервера. Если используется специальное значение syslog, то сообщения будут посылаться в системный журнал. На Unix системах это syslog(3), на Windows NT — журнал событий. Системный журнал не поддерживается в Windows 95. См. также: syslog() . Если директива не задана, ошибки будут направляться в SAPI журналы. Например, это могут быть журналы ошибок Apache или поток stderr командной строки CLI. Смотрите также функцию error_log() .

Источник

Читайте также:  Lumax приставка обновление прошивки

Adblock
detector

Cover image for Laravel Static Code Analysis with PHPStan

Muhammad Hassan

Code analysis is the process of testing and evaluating a program either statically or dynamically.

Dynamic analysis is the process of testing and evaluating a program — while software is running. It addresses the diagnosis and correction of bugs, memory issues, and crashes of a program during its execution. While static code analysis is a method of evaluating a program by examining the source code before its execution. It is done by analyzing a set of code against a set of coding rules.

Static analysis takes place before software testing begins. It guarantees that the code you pass on to testing is the highest quality possible. It also provide an automated feedback loop so the developers will know early on which in turn make it easier, and cheaper, to fix those problems.

Code analysis is the process of testing and evaluating a program either statically or dynamically.

Dynamic analysis is the process of testing and evaluating a program — while software is running. It addresses the diagnosis and correction of bugs, memory issues, and crashes of a program during its execution. While static code analysis is a method of evaluating a program by examining the source code before its execution. It is done by analyzing a set of code against a set of coding rules.

Static analysis takes place before software testing begins. It guarantees that the code you pass on to testing is the highest quality possible. It also provide an automated feedback loop so the developers will know early on which in turn make it easier, and cheaper, to fix those problems.

In this tutorial we are going to discuss:

  • Code Analysis Jargons

    • Measurements
    • Code Structure
    • Complexity
    • Security Issues
  • What Does PHPStan Bring?

    • Running PHPStan for the First Time
    • Rule Levels
  • How to Use PHPStan?

    • Installation
    • Configuration File
    • Ignoring Errors
    • The Baseline
    • Adding PHPStan to your CI/CD
  • Limitations of Static Analysis
  • Helpful Links

Code Analysis Jargons

Before moving to PHPStan, or any other tool, we need to be familiar with the terms that are commonly used in the code analyzation world. You can also think of them as what the tools will be looking for in your software.

Measurements

— Naming
Checking if variables and methods’ names, are they too short or too long? Do they follow a naming convention like camel-case?

— Type Hinting
Some tools can suggest a name consistent with the return type. For example a getFoo() method that returns a boolean is better be named isFoo().

— Lines of Code
Measures the line of codes in your class or method against a maximum value. In addition to the number of method’s parameter or class’ number of public methods and properties.

— Commented Code
Most of the time no commented out block of code will be allowed, as long as you are using a version control system, you can remove unused code and if needed, it’s recoverable.

— Return Statements
How many return statements do you have through out your method? Many return statements make it difficult to understand the method.

— Return Types
Makes sure that return type matches the expected. Having many return types possibilities confuses the analyzers.

Code Structure

— Dedicated Exceptions
Ensure the use of dedicated exceptions, instead of generic run-time exceptions, that can be cached by client code.

— No Static Calls
Avoid using static calls in your code and instead use dependency injection. Factory methods is the only exception.

— DRY
Checks for code duplication either in repeating literal values or whole blocks of code.

Complexity

Having a lot of control structures in one method AKA the pyramid of doom. Possible fixes include:

  • Early return statements
  • Merging nested if statements in combination with helper functions that make the condition readable

Security Issues

— Cipher Algorithms
Ensure the use cryptographic systems resistant to cryptanalysis, which are not vulnerable to well-known attacks like brute force attacks for example.

— Cookies
Always create sensitive cookies with the “secure” flag so it’s not sent over an unencrypted HTTP request.

— Dynamic Execution
Some APIs allow the execution of dynamic code by providing it as strings at runtime. Most of the time their use is frowned upon as they also increase the risk of code injection.


What Does PHPStan Bring?

Running PHPStan for the First Time

I have been using SonarQube for quite long time but when I first came across PHPStan repo I found this arguable claim…

PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code can be checked before you run the actual line.
So to put it to the test, I installed PHPStan in an application that has been analyzed with SonarQube since day one and the results were impressive

Image Test results
PHPStan has many rule levels, and as you can see, the higher the level we select the more errors we get with a maximum of 516 errors. Now the question is, which level should we select? Well first we need to know what are the rules of each level.

Rule Levels

Level Name Details
00 Basic Checks Checks for Unknown classes, unknown functions, unknown methods called on $this, wrong number of arguments passed to those methods and functions, always undefined variables.
01 $this Unknowns Possibly undefined variables, unknown magic methods and properties on classes with __call and __get.
02 Methods Unknown methods checked on all expressions (not just $this), validating PHPDocs.
03 Types Checks for return types, types assigned to properties.
04 Dead Code Basic dead code checking — always false instanceof and other type checks, dead else branches, unreachable code after return; etc.
05 Arguments Checking types of arguments passed to methods and functions.
06 Type Hints Reports missing type hints.
07 Union Types Reports partially wrong union types, if you call a method that only exists on some types in a union type, level 7 starts to report that.
08 Nullable Types Report calling methods and accessing properties on nullable types.
09 Mixed Type Be very strict about the mixed type, the only allowed operation you can do with it is to pass it to another mixed.

How to Use PHPStan?

Installation

To use PHPStan with Laravel we are going to use Larastan extension. Extensions are useful when there are subjective bugs or to accommodate to a certain framework while taking advantage of PHPStan capabilities.

  1. First we install the package with composer
   composer require nunomaduro/larastan:^2.0 --dev

Enter fullscreen mode

Exit fullscreen mode

Note: This version requires PHP 8.0+ and Laravel 9.0+

  1. Then you can start analyzing your code with the console command using the default configuration of PHPStan
   ./vendor/bin/phpstan analyse app --memory-limit=25

Enter fullscreen mode

Exit fullscreen mode

Here we specified the path that we want to analyze app and the memory limit 25 MB. You can find all the options of the command line here.

Configuration File

PHPStan uses configuration file, phpstan.neon or phpstan.neon.dist, that allows you to:

  • Define the paths that will be analyzed.
  • Set the rule level.
  • Exclude paths.
  • Include PHPStan extensions.
  • Ignore errors.
  • Define the maximum number of parallel processes

Here is an example of a simple configuration file which by default lives in the root directory of your application but you can learn more from the configuration reference.

includes:
    - ./vendor/nunomaduro/larastan/extension.neon

parameters:

    paths:
        - app
        - config
        - database
        - routes

    # The level 9 is the highest level
    level: 5

    ignoreErrors:
        - '#PHPDoc tag @var#'

    parallel:
        maximumNumberOfProcesses: 4

    noUnnecessaryCollectionCall: false
    checkMissingIterableValueType: false

Enter fullscreen mode

Exit fullscreen mode

Ignoring Errors

Most probably, you are going to need to ignore some errors which is luckily allowed in two different ways:

  1. Inline using PHPDoc tags
   function () {
       /** @phpstan-ignore-next-line */
       echo $foo;

       echo $bar /** @phpstan-ignore-line */
   }

Enter fullscreen mode

Exit fullscreen mode

  1. From the configuration file and this is actually more clean
     parameters:

         ignoreErrors:

             -
                 message: 'Access to an  undefined property [a-zA-Z0-9_]+::$foo'
                 path: some/dir/someFile.php
             -
                 message: '#Call to an undefined method [a-zA-Z0-9_]+::doFoo()#'
                 path: other/dir/DifferentFile.php
                 count: 2 # optional, and it will ignore the first two occurances of the error
          -
                 message: '#Call to an undefined method [a-zA-Z0-9_]+::doBar()#'
                 paths:
                     - some/dir/*
                     - other/dir/*

Enter fullscreen mode

Exit fullscreen mode

The Baseline

Introducing PHPStan to the CI pipeline, increasing strictness level or upgrading to a newer version can be overwhelming. PHPStan allows you to declare the currently reported list of errors as “the baseline” and stop reporting them in subsequent runs. It allows you to be interested in violations only in new and changed code.

If you want to export the current list of errors and use it as the baseline, run PHPStan with --generate-baseline option

./vendor/bin/phpstan analyse --memory-limit=25 --generate-base

Enter fullscreen mode

Exit fullscreen mode

Note: We dropped the path option from the example in installation as it is now being set in the config file.

It will generate the list of errors with the number of occurrences per file and saves it in phpstan-baseline.neon. Finally we add the baseline file to our includes

includes:
    - ./vendor/nunomaduro/larastan/extension.neon
    - phpstan-baseline.neon

Enter fullscreen mode

Exit fullscreen mode

Adding PHPStan to Your CI/CD

Adding PHPStan to the CI/CD pipeline and running it regularly on merge requests and main branches will increase your code quality. In addition to helping in code review.

Embed this snippet in your gitlab-ci.yml file and a code quality report will be generated for any merge request, changes to develop or master branches in addition to release and hotfix branches.

stages: 
  - staticanalysis - 

phpstan:
  stage: staticanalysis
  image: composer
  before_script:
    - composer require nunomaduro/larastan:1.0.2 --dev --no-plugins --no-interaction --no-scripts --prefer-dist --ignore-platform-reqs
  script:
    - vendor/bin/phpstan analyse --no-progress --error-format gitlab > phpstan.json
  cache:
    key: ${CI_COMMIT_REF_SLUG}-composer-larastan
    paths:
      - vendor/
  artifacts:
    when: always
    reports:
      codequality: phpstan.json
  allow_failure: true
  dependencies:
    - php-cs-fixer
  needs: 
    - php-cs-fixer
  only:
    - merge_requests
    - master
    - develop
    - /^release/[0-9]+.[0-9]+.[0-9]$/
    - /^hotfix/[0-9]+.[0-9]+.[0-9]$/

Enter fullscreen mode

Exit fullscreen mode


Limitations of Static Analysis

Static analysis is not a substitute for testing, they are different tools targeting different domains in the development lifecycle, and it has some limitation:

  • No Understanding of Developer Intent
  function calculateArea(int $length, int $width): int
  {
      $area = $length + $width;

      return;
  }

Enter fullscreen mode

Exit fullscreen mode

In the above function, a static code analysis tool might detect that the returned value does not match the defined type but it cannot determine that the function is semantically wrong!

  • Some rules are subjective depending on the context.
  • False Positives and False Negatives.

Helpful Links

  • Laravel-specific rules
  • Errors to ignore

  • PHPDocs usage with PHPStan

  • List of analysis tools for different languages

Понравилась статья? Поделить с друзьями:
  • Pip fatal error python h no such file or directory
  • Phpmyadmin ошибка incorrect format parameter
  • Pip error exception traceback most recent call last
  • Phpmyadmin ошибка 2002
  • Pip error could not find a version that satisfies the requirement