PHPackages                             phptramp/phptramp - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [DevOps &amp; Deployment](/categories/devops)
4. /
5. phptramp/phptramp

ActiveLibrary[DevOps &amp; Deployment](/categories/devops)

phptramp/phptramp
=================

Static analyzer that detects tramp data: parameters passed through chains of PHP methods that never use them.

v0.1.0(yesterday)154↑2622.2%MITPHPPHP &gt;=8.2

Since Aug 14Pushed yesterdayCompare

[ Source](https://github.com/larspohlmann/phptramp)[ Packagist](https://packagist.org/packages/phptramp/phptramp)[ RSS](/packages/phptramp-phptramp/feed)WikiDiscussions develop Synced today

READMEChangelog (1)Dependencies (6)Versions (3)Used By (0)

phptramp
========

[](#phptramp)

> Detect **tramp data** in PHP codebases: parameters that get passed through chains of methods that never use them — "this parameter was passed through 4 classes / 5 methods before being used."

[![CI](https://github.com/larspohlmann/phptramp/actions/workflows/ci.yml/badge.svg)](https://github.com/larspohlmann/phptramp/actions/workflows/ci.yml)[![Latest Version](https://camo.githubusercontent.com/6ce3cb0092aa40667735fc08d51c73cb7c346b81d66bdf9fb1e79f0489a6c209/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068707472616d702f7068707472616d70)](https://packagist.org/packages/phptramp/phptramp)[![PHP ≥ 8.2](https://camo.githubusercontent.com/51d3c1e23bc7e6efde7821bb122cad724a3c0705ec0e59a8c952ee94eb84e314/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d254532253839254135253230382e322d373737626233)](composer.json)[![License: MIT](https://camo.githubusercontent.com/b8cadaa967891081f8f165695470689986c028821dd8a040132f6e661795dc0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c7565)](LICENSE)

What it does
------------

[](#what-it-does)

```
$ vendor/bin/phptramp --folder src --limit 3

FINDING  $config: 3 pass-through hops across 4 classes
  origin    App\Http\Controller::handle($config)     src/Http/Controller.php:21→23
  hop 2     App\Service\ServiceA::process($config)   src/Service/ServiceA.php:14→16
  hop 3     App\Service\ServiceB::run($config)       src/Service/ServiceB.php:9→11
  terminal  App\Mail\Mailer::__construct($config)    src/Mail/Mailer.php:12  (stored)

```

The origin is hop 1, so a 3-hop chain runs origin → hop 2 → hop 3 → terminal; the summary counts the origin. Add `--explain` to see, per edge, how each call was resolved.

A **hop** is a method that receives a parameter and *purely forwards* it — never reads a property, never calls a method on it, never uses it in an expression. Long hop chains are the "tramp data" smell: every method in the middle is coupled to a value it has no business knowing about. The fix is usually a parameter object, a context object, or dependency injection at the terminal — this tool tells you *where*.

Construction and delegation don't count: a constructor forwarding to `parent::__construct()` (or any `parent::` call) is the same object handling its own value, so that node scores neither a hop nor a class and is marked `(parent)` in the chain.

Diff-aware CI mode
------------------

[](#diff-aware-ci-mode)

The flagship feature is diff-aware CI mode: run it on a pull request and it reports **"your edit made this chain longer"**, marking exactly which hops are yours. `--changed-only` restricts findings to chains that intersect a diff — a hop matches iff its declaration line or its forwarding call-site line was touched — and each matching hop's location line grows a `*YOURS*` annotation:

```
$ vendor/bin/phptramp --folder src --changed-only --git-base origin/main

FINDING  $config: 3 pass-through hops across 4 classes
  origin    App\Http\Controller::handle($config)    src/Http/Controller.php:21→23
  hop 2     App\Service\ServiceA::process($config)  src/Service/ServiceA.php:14→16  *YOURS*
  hop 3     App\Service\ServiceB::run($config)      src/Service/ServiceB.php:9→11
  terminal  App\Mail\Mailer::__construct($config)   src/Mail/Mailer.php:12  (stored)

1 finding (limit: 3 hops).

```

The `→N` after a hop's `file:line` is the **forwarding call-site line** — the line inside that method where the parameter is forwarded on. Terminal hops have no forwarding call, so they show only `file:line`. When a method forwards the same parameter to the same callee via multiple call sites, each produces its own finding distinguished by this `→N` value.

`--git-base ` (default `origin/main`) supplies the diff via `git diff --unified=0 ...HEAD` (three-dot, merge-base semantics); `--diff `reads a unified diff from a file, or from stdin with `-`, instead — either always implies `--changed-only`. See [docs/ci.md](docs/ci.md) for GitHub Actions and GitLab recipes.

Installation
------------

[](#installation)

```
composer require --dev phptramp/phptramp
```

### `composer tramp`

[](#composer-tramp)

Add a script to your project's `composer.json` to invoke it the short way:

```
{
    "scripts": {
        "tramp": "phptramp --folder src"
    }
}
```

```
composer tramp
composer tramp -- --format json --warn-limit 2
```

This repository gates itself with exactly this script — see its own [`phptramp.dist.json`](phptramp.dist.json).

CLI
---

[](#cli)

```
phptramp [options]

  --folder             Analyze all .php files under  (repeatable)
  --file              Analyze a single file
  --files            Comma-separated list of files
  --limit                Fail on chains with >= n pass-through hops (default: 6)
  --warn-limit           Warn (do not fail CI) on chains with >= n hops (default: 4; 0 = off)
  --min-classes          Only report chains traversing >= n distinct classes (default: 0 = off)
  --format             text|pretty|json|github|checkstyle|sarif|summary (default: pretty on TTY, text otherwise)
  --color             always|auto|never (default: auto; honors NO_COLOR in auto mode)
  --explain                 Show why chains ended (call resolution trace)
  --exclude-terminal  Do not report chains ending in  (repeatable; used|stored|&-terminated|unused-end|external|truncated -- quote '&-terminated', or the shell backgrounds the command)
  --changed-only            Only report chains touching changed lines
  --git-base           Diff base for --changed-only (default: origin/main)
  --diff            Read the diff from a file, or stdin with '-' (implies --changed-only)
  --baseline          Ignore findings recorded in the baseline file
  --generate-baseline    Write current findings to a baseline file
  --fail-on-stale           Exit 1 when stale baseline entries or stale suppressions are found
  --no-cache                Disable the per-file index cache (re-parse every file)
  --no-config               Ignore phptramp.json / phptramp.dist.json (drive everything from flags)
  --dump-index              Print the classified method index as JSON and exit

```

Exit codes: `0` no finding at error severity, `1` at least one finding at/over `--limit`, `2` tool error — so it drops straight into any CI pipeline.

Configuration
-------------

[](#configuration)

phptramp reads `phptramp.json` (falling back to `phptramp.dist.json`) from the current working directory; CLI flags always win. All keys, the index cache, and performance numbers are documented in [docs/configuration.md](docs/configuration.md).

```
{
    "paths": ["src"],
    "limit": 3,
    "warnLimit": 2
}
```

Output formats
--------------

[](#output-formats)

`--format` selects the renderer; all seven are implemented and each has an exact-string unit test.

`pretty` is the default on a TTY; pipes and CI fall back to `text` automatically. `--color=always|auto|never` overrides (`NO_COLOR` is honored in `auto` mode).

FormatOne-line example`pretty``src/Demo.php` (bold-blue file header) / `FINDING  $config: 3 pass-through hops across 4 classes` (colored, grouped by file)`text``FINDING  $config: 3 pass-through hops across 4 classes``json``{"limit":3,"warnLimit":null,"findings":[{"param":"config","severity":"error","hops":3,...}]}``github``::error file=src/Demo.php,line=12,title=phptramp%3A%3A$config%3A 3 pass-through hops across 4 classes (terminal%3A Demo\Mailer%3A%3A__construct [stored])``checkstyle````sarif``{"ruleId":"phptramp.trampData","level":"error","message":{"text":"$config: 3 pass-through hops across 4 classes (terminal: Demo\\Mailer::__construct [stored])"}}``summary``12 chains total; 5 at or over the limit (limit: 3 hops).`In a `--changed-only` run, each `json` chain entry additionally carries a `"changed": true|false` field marking whether that hop intersects the diff; a normal full run omits the field entirely rather than sending it as always-`false` noise.

Suppression
-----------

[](#suppression)

Mark a specific false positive as intentional instead of raising `--limit` project-wide:

- **`#[TrampIgnore]`** on a class, method, function, or parameter. Matching is by the attribute name's *short name*, so an analyzed codebase never has to `require` or autoload phptramp's own `PhpTramp\Ignore\TrampIgnore` class to use it.
- **`// phptramp-ignore`** as a real PHP comment (a marker inside a string literal does not count) on a hop's declaration line, the line directly above it, or a forwarding call-site line.

Either drops the *entire chain* passing through that hop, not just the one parameter reaching the flagged declaration.

`--warn-limit`
--------------

[](#--warn-limit)

`--warn-limit ` adds a second, lower threshold below `--limit`. Chains whose hop count falls in `[warn-limit, limit)` render at `severity: "warning"` (`WARNING` in text, `::warning` in the GitHub format, `"level": "warning"` in SARIF, …) but never fail the run — only chains at or over `--limit` set exit code `1`. Useful for tightening a hop budget gradually: warn today, promote to a hard failure once the codebase is clean.

`0` disables the warn tier entirely (no warnings emitted); `--limit 0` likewise disables the fail tier, leaving only warnings. `--min-classes ` is a complementary filter: it suppresses any chain traversing fewer than `n` distinct classes regardless of severity, so you can scope a noisy warn tier to genuinely wide chains.

Baseline
--------

[](#baseline)

Adopting phptramp on a codebase with existing tramp data? `--baseline`snapshots today's findings so CI only gates *new* chains, with refactor-stable fingerprints that survive renames and moved lines — and `--fail-on-stale` nudges you to prune entries as you fix them. The full workflow is in [docs/baseline.md](docs/baseline.md).

IDE integration
---------------

[](#ide-integration)

PhpStorm (and any IDE with external-tool support) can run phptramp per file via `--file`; a documented External Tool + File Watcher recipe is in [docs/phpstorm.md](docs/phpstorm.md). `--format=checkstyle` and `--format=sarif`cover CI annotation ecosystems, including GitHub Code Scanning.

Non-goals
---------

[](#non-goals)

- **No auto-fix.** Fixing tramp data means refactoring (parameter objects, DI rewiring), which is not mechanically safe. phptramp reports; you decide.
- **No second production dependency.** `nikic/php-parser` is the only one, deliberately.

Contributing
------------

[](#contributing)

Contributions are welcome — see the [contributing guide](.github/CONTRIBUTING.md) for the workflow and the CI gates, and the [code of conduct](CODE_OF_CONDUCT.md). Bugs are best reported with the [bug report form](https://github.com/larspohlmann/phptramp/issues/new?template=bug_report.yml).

License
-------

[](#license)

[MIT](LICENSE)

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance100

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 98.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

1d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3206468?v=4)[Lars Pohlmann](/maintainers/larspohlmann)[@larspohlmann](https://github.com/larspohlmann)

---

Top Contributors

[![larspohlmann](https://avatars.githubusercontent.com/u/3206468?v=4)](https://github.com/larspohlmann "larspohlmann (124 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (2 commits)")

---

Tags

devstatic analysiscode qualitycitramp data

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/phptramp-phptramp/health.svg)

```
[![Health](https://phpackages.com/badges/phptramp-phptramp/health.svg)](https://phpackages.com/packages/phptramp-phptramp)
```

###  Alternatives

[deptrac/deptrac

Deptrac is a static code analysis tool that helps to enforce rules for dependencies between software layers.

3.0k9.8M231](/packages/deptrac-deptrac)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[tempest/framework

The PHP framework that gets out of your way.

2.3k37.6k20](/packages/tempest-framework)[cakephp/bake

Bake plugin for CakePHP

11212.2M222](/packages/cakephp-bake)[boundwize/structarmed

Configurable PHP architecture guards — define your layers and rules, then keep them enforced

45751.2k23](/packages/boundwize-structarmed)[dereuromark/cakephp-ide-helper

CakePHP IdeHelper Plugin to improve auto-completion

1892.4M48](/packages/dereuromark-cakephp-ide-helper)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
