PHP command-line dependency analyzer. Extracts and visualizes all class relationships in a project: inheritance, interfaces, traits, injections, instantiations, static calls, docblocks.
git clone <repo>
cd php-dep
composer install
chmod +x bin/php-depFor global access:
ln -s /absolute/path/to/bin/php-dep /usr/local/bin/php-dep# Analyze the current directory
./bin/php-dep analyze
# Analyze a specific project
./bin/php-dep analyze /path/to/project/src
# JSON output (for scripts, CI, jq…)
./bin/php-dep analyze src/ --format=json -q
# Zoom in on a class
./bin/php-dep analyze src/ --class='App\Service\UserService'php-dep analyze [<path>] [options]
<path> is optional, defaults to .
| Option | Shortcut | Description |
|---|---|---|
--format=text|json |
-f |
Output format (default: text) |
--class=FQCN |
-c |
Focus on a class (full FQCN) |
--sort=alpha|deps|fanin |
-s |
Table sort: alphabetical, number of outgoing dependencies, number of incoming dependencies (default: alpha) |
--limit=N |
-l |
Limit output to N classes |
--exclude=dir |
Exclude a directory (can be used multiple times) | |
--include-vendor |
Include the vendor/ directory in the analysis |
|
--skip-docblocks |
Ignore @param/@return/@throws annotations |
|
--quiet |
-q |
Suppresses the progress bar and warnings (stdout preserved) |
--verbose |
-v |
Show warning details |
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Parsing error(s) |
2 |
Internal error |
3 |
Invalid arguments |
./bin/php-dep analyze src/Displays a table with, for each class: type, number of outgoing dependencies (what it uses), incoming dependencies (what uses it), and source file.
# Highest dependency consumers
./bin/php-dep analyze src/ --sort=deps --limit=10
# Most used by others (high fan-in)
./bin/php-dep analyze src/ --sort=fanin --limit=10./bin/php-dep analyze src/ --class='PhpDep\Parser\PhpFileParser' -vDisplays two tables: what the class uses (outgoing dependencies) and who uses it (incoming dependencies), with the relationship type and source line.
# Count classes
./bin/php-dep analyze src/ -f json -q | jq '.meta.class_count'
# List all inheritance relationships
./bin/php-dep analyze src/ -f json -q | jq '[.edges[] | select(.type == "extends")]'
# Find classes with no dependants (leaves)
./bin/php-dep analyze src/ -f json -q | jq '[.classes[] | select(.dependants | length == 0) | .fqcn]'
# Find dependencies of a specific class
./bin/php-dep analyze src/ -f json -q | jq '.classes[] | select(.fqcn == "App\\Service\\UserService") | .dependencies'./bin/php-dep analyze . --exclude=tests --exclude=fixtures --exclude=migrationsBy default, vendor/ is excluded from the analysis but third-party classes appear as external nodes in the graph. No additional option is needed to ignore them entirely.
To analyze the vendor itself:
./bin/php-dep analyze . --include-vendor| Type | Description |
|---|---|
extends |
Class or interface inheritance |
implements |
Interface implementation |
uses_trait |
Trait usage |
param_type |
Type hint on a method parameter |
return_type |
Method return type |
property_type |
Class property type |
instantiates |
new Foo() |
static_call |
Foo::method() |
static_property |
Foo::$prop |
const_access |
Foo::CONST |
instanceof |
$x instanceof Foo |
catches |
catch (FooException $e) |
Extracted from @param, @return, @var, @throws. Confidence: high.
| Type | Source |
|---|---|
docblock_param |
@param FooType $x |
docblock_return |
@return FooType |
docblock_var |
@var FooType |
docblock_throws |
@throws FooException |
| Value | Meaning |
|---|---|
certain |
Structural relationship guaranteed by the AST |
high |
Docblock, highly probable |
medium |
Ambiguous pattern (instanceof) |
low |
Dynamic pattern |
| Type | Trigger |
|---|---|
dynamic_instantiation |
new $variable() — class unknown at static analysis time |
dynamic_call |
Unresolvable dynamic call |
parse_error |
Invalid or unreadable PHP file |
Warnings are printed to stderr. The JSON output includes them in warnings[]. With -v, the text output lists them at the end of the report.
- Discovery:
git ls-filesif inside a git repository, otherwiseRecursiveDirectoryIterator. Thevendor/,node_modules/, and.git/directories are excluded by default. - Parsing: nikic/PHP-Parser v5. The
NameResolverruns first in the traverser: all downstream names are resolved FQCNs. - Docblocks: phpstan/phpdoc-parser for
@param,@return,@var,@throws. - Memory: each file's AST is freed immediately after extraction (streaming). Only one AST in memory at a time.
- Vendor: in
boundarymode (default), vendor classes areexternalnodes (leaves) — their files are not analyzed.
- PHP >= 8.2
- Composer
{ "meta": { "version": "1.0", "generated_at": "2026-02-26T10:00:00+00:00", "analyzed_path": "/path/to/project", "file_count": 42, "class_count": 38, // internal nodes only "node_count": 95, // internal + external (vendor, built-in) "edge_count": 312, "warning_count": 2 }, "classes": [ { "fqcn": "App\\Service\\UserService", "type": "class", // class | interface | trait | enum "file": "/path/to/UserService.php", "line": 12, "dependencies": ["App\\Repository\\UserRepository", "Psr\\Log\\LoggerInterface"], "dependants": ["App\\Controller\\UserController"] } ], "edges": [ { "source": "App\\Service\\UserService", "target": "App\\Repository\\UserRepository", "type": "param_type", // see relationship types below "confidence": "certain", // certain | high | medium | low "file": "/path/to/UserService.php", "line": 23, "metadata": {} } ], "warnings": [ { "type": "dynamic_instantiation", "file": "/path/to/Factory.php", "line": 45, "message": "Dynamic instantiation: new $variable()" } ] }