# PHPStan: восемь задач статического анализа

PHPStan **2.3.5**, Composer lock, PHP >=8.2 для исходников лаборатории. Установленный анализатор поддерживает другие версии PHP, но примеры проекта используют возможности PHP8.2. В конфигурации `phpVersion: 80200` — целевая версия анализируемого кода, отдельно от версии PHP, которая запускает инструмент. Bootstrap5.3.9 локальный.

Восемь тем, девятнадцать вариантов реального CLI. Мастерская показывает **запись выполнения PHPStan**, а не запускает анализатор в браузере. Выберите «до/после», уровень или baseline, сообщение и его строку. Произвольный PHP можно проверить локально по командам ниже.

## Windows / PowerShell

```powershell
php -v
composer install --no-interaction --no-plugins --no-scripts
php vendor/bin/phpstan --version
php vendor/bin/phpstan analyse --configuration=phpstan.neon --level=9 --no-progress cases/methods/before.php
$LASTEXITCODE  # 1: намеренно ошибочный учебный файл
php vendor/bin/phpstan analyse --configuration=phpstan.neon --level=9 --no-progress cases/methods/after.php
$LASTEXITCODE  # 0
php tests/run.php
php bin/ci.php
php bin/build-public.php
```

На Windows явно вызываем PHP, чтобы не зависеть от выбора shell для vendor/bin. Composer dev-зависимости нужны для анализа: `--no-dev` удалит сам PHPStan. Не анализируйте vendor и var. Папки cases/*/before.php и fixtures намеренно содержат нарушения и не являются рабочим приложением.

## Linux / Bash

```bash
php -v
composer install --no-interaction --no-plugins --no-scripts
php vendor/bin/phpstan analyse --configuration=phpstan.neon --level=9 --no-progress cases/nullable/before.php
echo "$?" # 1
php vendor/bin/phpstan analyse --configuration=phpstan.neon --level=9 --no-progress cases/nullable/after.php
echo "$?" # 0
php tests/run.php recording-linux.json
php bin/ci.php
php bin/build-public.php
```

Запускайте от обычного пользователя. Версия PHP для CLI, target phpVersion и версия PHP-FPM — отдельные настройки. Для CI подробнее docs/LINUX-CI.md. Команды before в примерах предназначены для наблюдения отказа; не вставляйте их в рабочий pipeline, ожидающий только успех.

## Настоящий baseline

`Runner::collect()` сначала выполняет настоящую команду PHPStan `--generate-baseline=config/phpstan-baseline.neon` только для `fixtures/legacy.php`. Полученный файл сохраняется и включается в config/with-baseline.neon. Он ограничивает известную ошибку путём, identifier и количеством. Затем анализ запускается без baseline, с baseline и с baseline плюс новым ошибочным файлом. В последнем варианте ошибка остаётся видимой.

```bash
php vendor/bin/phpstan analyse --configuration=phpstan.neon --level=9 --generate-baseline=config/phpstan-baseline.neon fixtures/legacy.php
php vendor/bin/phpstan analyse --configuration=config/with-baseline.neon --level=9 fixtures/legacy.php fixtures/new-error.php
```

Не добавляйте генерацию baseline в обычную проверку рабочего CI: так можно принять новый долг автоматически. Здесь она часть изолированного воспроизводимого опыта. Для своего проекта baseline создают осознанно, проверяют diff и постепенно сокращают. `reportUnmatchedIgnoredErrors: true` оставлен включённым.

## Что реально проверяется

В каждом варианте записаны команда, config, level, exit code, JSON stdout/stderr, сообщения с line/identifier и source SHA256. В публичном выводе только абсолютный путь проекта заменён на `[project]`, а CRLF нормализован в LF; ошибки не выдуманы. Исходники доступны рядом.

Тесты повторно запускают все девятнадцать анализов, проверяют коды и привязку к строкам. Отдельные runtime-пробы вызывают исправленный JSON-parser/null-ветку и намеренно подавленный аргумент: у suppressed exit0 анализатора, но настоящий TypeError при выполнении. Поэтому отсутствие сообщений не означает исправление программы.

`bin/ci.php` анализирует **семь исправленных after.php**, а не все служебные файлы мастерской. Он возвращает настоящий код анализатора. Перед переносом в свой проект замените scope на src/tests и настройте автозагрузку. PHPStan не является тестом безопасности, не исполняет бизнес-сценарии и не доказывает правильность API/SQL/прав доступа.

## Просмотр и структура

Готовую public можно раздать любым статическим HTTP-сервером. Например, `php -S 127.0.0.1:8534 -t public`; остановка Ctrl+C. file:// не поддерживается. На публичный хост публикуется только public, без анализатора и исполняемых PHP-фикстур. Посетитель не может отправить код на сервер этой мастерской.

- src/Cases.php: фиксированные сценарии и варианты.
- src/Runner.php: реальные CLI-процессы без shell-интерполяции.
- cases/: до, после и учебное подавление.
- fixtures/: намеренные старые и новые ошибки baseline.
- tests/run.php: анализ и ограниченные runtime-пробы.
- public/recording*.json: подтверждённый вывод Windows/Linux.

Официальные источники: https://phpstan.org/user-guide/getting-started ; https://phpstan.org/user-guide/rule-levels ; https://phpstan.org/user-guide/baseline ; https://phpstan.org/writing-php-code/phpdoc-types ; https://phpstan.org/blog/generics-in-php-using-phpdocs . Авторский код и PHPStan MIT; лицензии включены.
