denzyl/phanalist

Performant static analyzer for PHP, which is extremely easy to use. It helps you catch common mistakes in your PHP code.

Maintainers

Package info

github.com/denzyldick/phanalist

Language:Rust

pkg:composer/denzyl/phanalist

Statistics

Installs: 45 965

Dependents: 0

Suggesters: 0

Stars: 154

Open Issues: 0

v0.1.32 2026-06-10 03:09 UTC

README

Crates.io License: MIT CI

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 formatstext, json, and sarif (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

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 skip
  • rules — 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.

  1. Write your own static analyzer for PHP.
  2. How I made it impossible to write spaghetti code.
  3. Detecting spaghetti code in AST of a PHP source code.
  4. Getting Symfony app ready for Swoole, RoadRunner, and FrankenPHP (no AI involved).
  5. Improve your CI output
  6. Why using unserialize in PHP is a bad idea