---
title: "Sloppy: статичний аналіз PHP для коду, який пишуть AI-агенти"
url: https://laravelukraine.com/blog/sloppy-staticnii-analiz-php-dlia-kodu-iakii-pisut-ai-agenti
date: 2026-10-28
---

# Sloppy: статичний аналіз PHP для коду, який пишуть AI-агенти

Чимало PHP-коду тепер пишуть Claude Code, Codex чи Gemini CLI, і помилки в ньому мають свій почерк: порожній `catch`, що ховає збій, метод на двісті рядків, запит до бази всередині циклу, тіло методу, замінене коментарем `// ... existing code ...`. Типи при цьому сходяться, форматування бездоганне, тож PHPStan і Pint мовчать. [Sloppy](https://github.com/heyosseus/sloppy) від розробника heyosseus - статичний аналізатор саме для таких проблем супроводу, про який цього тижня [написав Laravel News](https://laravel-news.com/sloppy).

Він детермінований і працює локально: жодної моделі, API-ключа чи мережі. Той самий код завжди дає той самий звіт.

### Що він перевіряє

За [README](https://github.com/heyosseus/sloppy) у пакеті 34 правила, ще три перевірки, що порівнюють зміну з її базою, і п'ять опційних правил для архітектури, яку ви описуєте самі. Основні групи:

- **складність і дублювання** - `SL101` God Method, `SL102` God Class, `SL104` Duplicate Logic, `SL111` Copy-Paste Drift (майже копія, чия єдина відмінність схожа на недороблене редагування);
- **мертвий код** - невикористані приватні методи й залежності конструктора, `SL112` Placeholder Implementation: заглушка або `throw new Exception('Not implemented')` замість тіла;
- **обробка помилок** - `SL107` Swallowed Exception;
- **Laravel** - бізнес-логіка в контролері, валідація прямо в дії, прямі виклики зовнішніх API, `SL203` Possible N+1, `SL204` Query Inside Loop, `SL205` Collection Instead Of Query;
- **маршрути й міграції** (з [версії 1.8.0](https://github.com/heyosseus/sloppy/releases/tag/v1.8.0)) - маршрут до методу контролера, якого не існує, GET-маршрут, що видаляє, міграція, яку відредагували після запуску, міграція без `down()`;
- **підозрілі тести** - `SL503` Weakened Test: тест пропущено, з нього прибрали перевірки або додали `assertTrue(true)`, щоб він пройшов.

Кожна знахідка має розташування, виміряні значення, рівень впевненості й пораду, що змінити.

### Два правила на прикладі

Ось архівація, яка тихо ковтає будь-яку помилку:

```php
try {
  Storage::disk('s3')->put("transcripts/{$sessionId}.txt", $transcript);
} catch (\Throwable $exception) {
}
```

Це `SL107`. Sloppy підкаже, що обробки бракує, але не вирішить за вас, що робити зі збоєм: залогувати, повторити чи дати винятку піти далі. Це залежить від операції.

Друге правило ловить фільтрацію в PHP того, що мала б відфільтрувати база:

```php
// SL205: завантажує всі записи, а потім фільтрує колекцію
$publishedCount = PodcastEpisode::all()
  ->where('status', 'published')
  ->count();

// так рахує база
$publishedCount = PodcastEpisode::query()
  ->where('status', 'published')
  ->count();
```

### Як підключити до агента

```bash
composer require --dev heyosseus/sloppy

vendor/bin/sloppy                  # у Laravel: php artisan sloppy
vendor/bin/sloppy agents install   # --host=gemini, --host=codex
```

Потрібен PHP 8.3 або новіший, а правила для Laravel вмикаються на Laravel 12 і 13. Конфігураційний файл не обов'язковий: каталоги з кодом Sloppy бере з `composer.json`.

`agents install` дописує правила проєкту в `CLAUDE.md` і додає два хуки в `.claude/settings.json`. Після кожного `Edit` чи `Write` PHP-файлу агент отримує знахідки, які внесло саме це редагування, порівняно з `HEAD`. Коли агент намагається завершити задачу, фінальний хук повертає його виправляти нові знахідки від заданого порогу. Знахідки, які файл мав і раніше, агентові не показують, щоб той не кидався «виправляти» код, якого його не просили чіпати. З `--local` хуки й правила йдуть в особисті `.claude/settings.local.json` і `CLAUDE.local.md`. Для агентів, які мають перевіряти код на вимогу, є MCP-сервер `vendor/bin/sloppy-mcp`.

### На старому проєкті - лише нове

Перший запуск на кодовій базі з історією знайде сотні дрібниць. Щоб вони не змішувалися з новими, є два режими відносно спільного предка гілки з `main`:

```bash
vendor/bin/sloppy diff main --merge-base
vendor/bin/sloppy review main --merge-base
```

`diff` показує лише те, що внесла гілка, `review` ще й сортує знахідки за ризиком, щоб було видно, який файл читати першим. Незакомічені файли теж враховуються, а знахідки прив'язані до відбитків, а не до номерів рядків, тож доданий `use` не робить стару проблему новою. `sloppy baseline` фіксує поточний борг, щоб збірку валили тільки нові знахідки. Механічні виправлення `sloppy:fix --dry-run` показує наперед і передає Rector, а потім форматує Pint. Обидва треба встановити в проєкт окремо.

### Де межі

- **Це не детектор AI.** Автор прямо пише, що за кодом не можна надійно визначити, хто його написав, і Sloppy не намагається. `Confidence: 88%` означає впевненість у тому, що шаблон справді є, а не ймовірність, що код згенерувала модель.
- **Хуки - зворотний зв'язок, а не гейт.** Фінальна перевірка блокує агента лише один раз: друга спроба завершити проходить, а невиправлене лишається в транскрипті. Якщо Sloppy не може запуститися, агент просто працює далі. Щоб нові знахідки валили збірку, потрібен `sloppy ci`, GitHub Action або Pest-перевірка `expectCleanSloppyDiff('main')`.
- **Евристики помиляються.** God Method, Duplicate Logic чи Narrative Comment - це оцінки, а не доведення. Автор пише, що правила налаштовані на тишу і що звичайний Laravel-код за тестами не дає жодної знахідки, але хибні спрацьовування він сам просить звітувати як баги.
- **Проєкт молодий.** Між 1.2.0 (28 вересня) і 1.8.0 (21 жовтня) минуло менше місяця, а у 1.8.0 змінилися типові налаштування: міграції більше не виключені за замовчуванням, хоча раніше опублікований `config/sloppy.php` досі їх виключає.

### Чи замінить він PHPStan

Ні, і сам не претендує. [PHPStan](https://laravelukraine.com/blog/phpstan-23-stribok-produktivnosti-pokrashheni-generics-i-viiavlennia-nevikoristanix-zminnix) і Psalm відповідають на питання, чи коректні типи, а Sloppy - чи схожий код на той, про який згодом пошкодують. README обіцяє, що де PHPStan може щось довести, Sloppy туди не лізе, а для тих, хто вже живе з PHPStan, є розширення `heyosseus/phpstan-sloppy`: ті самі знахідки як помилки PHPStan з ідентифікаторами на кшталт `sloppy.SL107`. Але частина правил перетинається зі знайомими інструментами: невикористані приватні методи й завжди істинні умови PHPStan частково ловить і сам, а N+1 у розробці добре видно через `Model::preventLazyLoading()`. Нове тут - насамперед проковтнуті винятки, заглушки, копії з дрібною відмінністю, ослаблені тести та міграції, відредаговані після запуску.

Якщо агенти пишуть у вас помітну частку коду, Sloppy варто спробувати: на окремій гілці запустіть `sloppy review main --merge-base`, подивіться, скільки знахідок справді корисні, і лише потім вмикайте хуки. А збірку довіряйте CI, не хукам.
