denzyl/phanalist 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

denzyl/phanalist

Composer 安装命令:

composer require denzyl/phanalist

包简介

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

README 文档

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 formatstext, json, sarif (for CI pipelines with inline PR annotations via GitHub Action), and codeclimate (for Code Quality platforms)
  • 🔌 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 1.0.0

There are also multiple other installation options.

GitHub Action

Add inline SARIF annotations to your PRs using the Phanalist GitHub Action:

name: Phanalist
on: [pull_request]
permissions:
  security-events: write
jobs:
  phanalist:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: denzyldick/phanalist-action@v1

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, -c Path to configuration file ./phanalist.yaml
--src, -s Path(s) to project sources (repeatable, e.g. -s src -s tests) ./src
--rules, -r Only run these rules (overrides config) from config
--output-format, -o Output format: text, json, sarif, codeclimate text
--summary-only Show only violation counts per rule
--quiet, -q Suppress all output
--verbose, -v Increase verbosity; repeat for more (-v main pass, -vv parsing, -vvv indexing)
--debug-rule-timing Print per-rule per-file timing (min/max/avg/p90/p95/p99 + slowest files)
--debug-rule-stats Print per-rule cost/coverage stats (time, %, violations, files, statements)
--use-baseline Filter results against a baseline file, reporting only new violations
--update-baseline Regenerate the baseline from the current scan (requires --use-baseline)
--blame Attribute violations to engineers via git blame and show a quality report
--since Only count violations from commits after this date (e.g. "30 days", "1 year", "2025-01-01")
--until Only count violations from commits before this date (e.g. "2025-06-01")
--export-chart Export engineer chart as PNG/SVG image (requires --blame)
--exclude-author Exclude authors from the report (repeatable, e.g. --exclude-author dependabot)
--min-violations Minimum total violations to include an engineer in the report 0
--lsp Start as a Language Server (LSP) for editor integrations

Engineer Quality Report

Use the --blame flag to see who is introducing and fixing violations in your codebase:

# Who has violations in their code currently
~/phanalist --blame

# See what changed in the last 30 days (Net column shows who is improving vs degrading)
~/phanalist --blame --since "30 days"

# See changes over the last year
~/phanalist --blame --since "1 year"

# Exclude bots
~/phanalist --blame --since "30 days" --exclude-author dependabot

# Sort by net improvements (who is adding the most value)
~/phanalist --blame --since "30 days" --sort net

The report shows a table with:

Column Meaning
Engineer Git author name
Fixed (✓) Violations that disappeared compared to the --since snapshot
Introduced (✗) Violations that appeared compared to the --since snapshot
Net Fixed - Introduced — positive means improving, negative means degrading

Sorting:

Use --sort to change the order: total (default, by volume), net (by net improvements), name, fixed, introduced.

How it works:

  • Without --since: Looks at the current violations in your code and uses git blame to figure out who last touched each affected line. Engineers are credited with the violations in code they most recently worked on.
  • With --since <date>: Takes a snapshot of your code as it was at that date, runs the same analysis on the old version, and compares the results. Violations that disappeared were "fixed" — violations that appeared were "introduced". Each change is attributed to the engineer who made it.

Output:

The report includes a summary table and a per-rule breakdown with colored counts (green for fixed, red for introduced).

The --blame flag works with --output-format json — the engineer data is included as an "engineer_report" field in the JSON output for use in pipelines or dashboards.

Requires a .git directory (discovered from the current working directory). Only files within --src paths are attributed.

Baseline

A baseline lets you adopt phanalist on an existing codebase without fixing every finding at once. It freezes the current violations; later runs report only new ones, so CI stays green on known debt but fails on regressions.

Generate (or regenerate) the baseline:

~/phanalist --use-baseline phanalist-baseline.json --update-baseline

Then run against it (in CI, or locally):

~/phanalist --use-baseline phanalist-baseline.json

The baseline is a pretty-printed, stably sorted JSON file, so it produces clean diffs and merges. Each entry is keyed on the file, rule, and a stable message id with a count, so unrelated edits that shift line numbers do not invalidate it, and reworded message text does not either. When you fix violations, regenerate the baseline to shrink it.

Configuration

enabled_rules: []   # empty = all rules active
disable_rules: []
exclude_paths: []   # paths skipped before any rule runs (see below)
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: []
    reset_interfaces:
      - "ResetInterface"
  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
  • exclude_paths — files skipped before any rule runs, as directory prefixes (var/cache, bootstrap/cache) or globs (**/*.generated.php). Handy for framework caches and frozen code like migrations that would only add noise. Literal (non-glob) patterns that don't exist on disk trigger a warning at -v verbosity — a helpful catch for typos. Globs that match nothing are silently accepted.

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.

🔌 Language Server Protocol (LSP)

Phanalist includes built-in LSP support to provide real-time, as-you-type diagnostics directly in your editor.

To start the language server, run:

phanalist --lsp

Editor Configuration Examples

Neovim (using vim.lsp)

Add the following to your init.lua or filetype plugin (ftplugin/php.lua):

vim.api.nvim_create_autocmd("FileType", {
  pattern = "php",
  callback = function()
    local root_dir = vim.fs.dirname(vim.fs.find({'phanalist.yaml', '.git'}, { upward = true })[1])
    if root_dir then
      vim.lsp.start({
        name = "phanalist-lsp",
        cmd = { "phanalist", "--lsp" },
        root_dir = root_dir,
      })
    end
  end,
})
VS Code

You can use any generic LSP extension or configure your settings to run phanalist --lsp as a language client for PHP files.

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

denzyl/phanalist 适用场景与选型建议

denzyl/phanalist 是一款 基于 Rust 开发的 Composer 扩展包,目前已累计 46.92k 次下载、GitHub Stars 达 160, 最近一次更新时间为 2024 年 02 月 05 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php」 「refactoring」 「static-analysis」 「linting」 「static analyzer」 「maintainability」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 denzyl/phanalist 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 denzyl/phanalist 我们能提供哪些服务?
定制开发 / 二次开发

基于 denzyl/phanalist 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 46.92k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 160
  • 点击次数: 24
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 160
  • Watchers: 3
  • Forks: 8
  • 开发语言: Rust

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-02-05