denzyl / phanalist
Performant static analyzer for PHP, which is extremely easy to use. It helps you catch common mistakes in your PHP code.
Suggests
- ext-curl: Recommended for downloading the binary
- ext-zip: Required to extract the binary on Windows
- dev-main
- v0.1.32
- v0.1.31
- v0.1.30
- v0.1.29
- v0.1.28
- v0.1.27
- 0.1.26
- 0.1.25
- 0.1.24
- v0.1.22
- v0.1.21
- v0.1.20
- v0.1.19
- dev-chore/update-mago-to-1.30
- dev-dependabot/cargo/mago-syntax-1.30.0
- dev-dependabot/cargo/mago-database-1.30.0
- dev-dependabot/cargo/mago-span-1.30.0
- dev-feat/migrate-to-mago-parser
- dev-advanced-project-analysis
This package is auto-updated.
Last update: 2026-06-10 03:36:30 UTC
README
Performant static analyzer for PHP, written in Rust. Catches common mistakes and enforces best practices with zero configuration required.
🤔 Why Phanalist?
PHP codebases grow. As they grow, they accumulate technical debt — god classes that do everything, methods no one can follow, hidden complexity that breaks with every change. Traditional linters catch syntax errors and style issues, but they don't tell you if your code is maintainable.
Phanalist focuses on structural health. It measures what matters for long-term maintainability:
- Complexity metrics — cyclomatic complexity, cognitive complexity, LOC per method, nested paths
- Coupling & cohesion — Law of Demeter violations, god classes, data classes, fan-in/fan-out
- Object-oriented design — depth of inheritance, weighted methods per class, response for a class
- Readability — comment ratios, error suppression, method parameter counts
Think of it as a health checkup for your PHP code. It doesn't just tell you that something is wrong — each rule explains why it matters and how to fix it.
✨ Features
- 🚀 Fast — built in Rust, analyzes large codebases in seconds
- 🔍 31 built-in rules — covering complexity, style, design patterns, and more
- ⚙️ Zero config to start — works out of the box, configure only what you need
- 📄 Multiple output formats —
text,json, andsarif(for CI pipelines) - 🔌 Extensible — adding a custom rule takes minutes
Installation
The simplest way to install Phanalist is to use the installation script:
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/denzyldick/phanalist/main/bin/init.sh | sh
It will automatically download the executable for your platform:
$ ~/phanalist -V
phanalist 0.1.29
There are also multiple other installation options.
Usage
To analyze your project sources, run:
~/phanalist
Example
On the first run phanalist.yaml will be created with the default configuration and reused on all subsequent runs.
Additional CLI flags:
| Flag | Description | Default |
|---|---|---|
--config |
Path to configuration file | ./phanalist.yaml |
--src |
Path to project sources | ./src |
--output-format |
Output format: text, json, sarif |
text |
--summary-only |
Show only violation counts per rule | — |
--quiet |
Suppress all output | — |
Configuration
enabled_rules: [] # empty = all rules active disable_rules: [] rules: E0007: check_constructor: true max_parameters: 5 E0009: max_complexity: 10 E0010: max_paths: 200 E0012: include_namespaces: - "App\\Service\\" - "App\\Controller\\" exclude_namespaces: [] E0015: threshold: 1 E0016: max_complexity: 15 E0024: max_loc: 30 E0025: max_loc: 500 E0026: min_ratio: 0.1 max_ratio: 0.5 E0027: max_methods: 15 max_fields: 10 E0028: max_getter_setter_ratio: 0.7 min_methods: 3 E0029: max_fan_out: 10 max_fan_in: 20 E0030: max_density: 0.3
enabled_rules— whitelist of rules to run (empty = all)disable_rules— rules to skiprules— per-rule configuration options
Rules
| Code | Name | Options |
|---|---|---|
| E0000 | Example rule | |
| E0001 | Opening tag position | |
| E0002 | Empty catch | |
| E0003 | Method modifiers | |
| E0004 | Uppercase constants | |
| E0005 | Capitalized class name | |
| E0006 | Property modifiers | |
| E0007 | Method parameters count | check_constructor: true, max_parameters: 5 |
| E0008 | Return type signature | |
| E0009 | Cyclomatic complexity | max_complexity: 10 |
| E0010 | Npath complexity | max_paths: 200 |
| E0011 | Detect error suppression symbol (@) |
|
| E0012 | Service compatibility with Shared Memory Model | include_namespaces, exclude_namespaces, reset_interfaces |
| E0013 | Private method not being used | |
| E0014 | Law of Demeter | |
| E0015 | Lack of Cohesion of Methods (LCOM4) | threshold: 1 |
| E0016 | Cognitive complexity | max_complexity: 15 |
| E0017 | Coupling Between Objects (CBO) | max_coupling: 10 |
| E0018 | Weighted Methods per Class (WMC) | max_wmc: 50 |
| E0019 | Response For a Class (RFC) | max_rfc: 50 |
| E0020 | Depth of Inheritance Tree (DIT) | max_depth: 4 |
| E0021 | Number of Children (NOC) | max_children: 15 |
| E0022 | Afferent and Efferent Coupling (Ca/Ce) | max_ca: 20, max_ce: 20 |
| E0023 | Instability, Abstractness, Distance (I/A/D) | max_instability: 0.8, max_abstractness: 0.8, max_distance: 0.5 |
| E0024 | Lines of Code per Method | max_loc: 30 |
| E0025 | Lines of Code per File | max_loc: 500 |
| E0026 | Comment Ratio | min_ratio: 0.1, max_ratio: 0.5 |
| E0027 | God Class (Brain Class) | max_methods: 15, max_fields: 10 |
| E0028 | Data Class | max_getter_setter_ratio: 0.7, min_methods: 3 |
| E0029 | Fan-in / Fan-out | max_fan_out: 10, max_fan_in: 20 |
| E0030 | Cyclomatic Complexity Density | max_density: 0.3 |
Adding a new rule is straightforward — this tutorial explains how.
Articles
Read a series of chapters on https://dev.to/denzyldick to understand the project's internals — a great, easy-to-read introduction.

