WordPress 的核心函数与类需要先通过 Composer 安装 php-stubs/wordpress-stubs 才能获得类型;框架支持依赖项目自身已有的代码,无需额外下载或配置;README 未给出编辑器端的具体接入配置,需参考官方文档。
phpantom_lsp
PHPantom-devMIT活跃维护用 Rust 写的高性能 PHP 语言服务器,提供泛型、Laravel 和 PHPStan 注解的深度类型推断,启动即用,适合在 Neovim、VS Code 等编辑器里获得快速准确的代码补全与跳转。
Fast PHP language server with deep type intelligence. Generics, Laravel, PHPStan annotations. Ready in an instant.
cargo install phpantom_lspREADME 未说明显存或 GPU 要求;性能测试显示在 5.1K PHP 文件的生产级 Laravel 代码库上常驻内存约 578 MB。
用 Rust 写的快速 PHP 语言服务器,专注深度类型推断,适合想要秒开且内存占用低的 PHP 工程师
用 Rust 写的高性能 PHP 语言服务器,提供泛型、Laravel 和 PHPStan 注解的深度类型推断,启动即用,适合在 Neovim、VS Code 等编辑器里获得快速准确的代码补全与跳转。
核心能力
- 用 Rust 实现,后台索引,缓存命中后约 2 秒就绪
- 支持泛型与 @template、数组形状、条件返回类型等 PHPDoc 高级类型
- 内置 Laravel、Symfony、WordPress、Drupal、Yii 3、PHPUnit 与 Pest 框架支持
- 在服务器内集成 PHPStan、PHPCS、PHPMD、Mago 并附带快速修复
- 提供重命名、提取与内联、生成构造函数与访问器、现代化语法改写
容易踩的坑
- 0.11.1最新正式版2026-10-07 · 2026-10-07 04:25 UTC
PHPantom 0.11.1
Highlights
New editor features
- Unreachable code is dimmed. Code that can never run, such as statements after a
returnorthrow, is greyed out the way an unused import is (@petrovo-as).
Laravel
- Translations across locales. Navigation, completion and hover work across JSON and PHP language files and every locale, and a missing key gets a quick fix when its PHP group file exists (@shuvroroy).
- Package translations. Paths registered with
loadTranslationsFrom()now support completion, navigation, hover and key diagnostics (@shuvroroy). - Config keys set by a package's provider. A key set with
config([...])orConfig::set()is known, soauth('sanctum')is no longer reported as an unknown guard.
Blade
- Fewer false syntax errors. An Alpine or Vue
:attrbinding on a plain HTML tag is no longer parsed as PHP, and a directive newer than your Laravel is plain text, so a JSON-LD"@context"key no longer produces syntax errors before Laravel 11. @breakand@continuekeep their condition.@break($done)and@continue($skip)now only jump when the condition holds.@useimports. The first import no longer breaks a template that opens with a block, unused imports are dimmed and removed byphpantom_lsp fix, and a group wrapped over several lines no longer shifts the lines below it.- Stable
analyzeoutput. Blade diagnostics no longer vary between runs and now match what the editor shows.
Type checking
match (true)arms know the arms above them.default => strtoupper($name)no longer reports$nameas possiblynull(@phcorp, #464).- Type checks narrow properties.
is_resource($this->stream)narrows aresource|nullproperty the way it narrows a variable (@phcorp, #466). - Integer
range()calls are lists of integers.array_map(fn (int $i) => …, range(0, $n - 1))no longer reports that the callback is passedint|float(@phcorp, #467). - More accurate narrowing.
in_array()only narrows by what the list proves,matcharms narrow the way the equivalentifdoes, and a ternary to the right of&&or||sees what the left side proved. - Unsealed array shapes are checked. A type such as
array{foo: int, ...}no longer accepts any non-empty array, and the entries it lists must fit the typed array it is passed to.
Code actions
- Safer class moves. In the editor and with
phpantom_lsp move, moves that would pull other declarations into the new namespace, or break a file with severalnamespaceblocks, are refused, and the rest touch only their own block. - Imports respect each
namespaceblock. In a file with severalnamespaceblocks, new imports go into the block that needs them, and an import only another block uses is dimmed as unused. - Member actions appear at column 0. Actions on a property or method, such as getter/setter and visibility, are now offered with the cursor at column 0 or on a whole-line selection.
Configuration and indexing
- PHP_CodeSniffer only runs where you use it. A
vendor/bin/phpcsinstalled by another package no longer produces warnings unlesssquizlabs/php_codesnifferis inrequire-dev, a ruleset file exists, or.phpantom.tomlsets[phpcs] standard. - laravel-ide-helper files are skipped.
_ide_helper.phpand_ide_helper_models.phpare no longer indexed, since PHPantom resolves facades and models natively; list them with a leading!in[indexing] excludeto index them anyway. - Files outside the project no longer break indexing. A PHP file opened from elsewhere, or a change in another workspace folder, no longer stops the server when the configuration changes.
Performance
- Blade indexing. Templates with no DocBlock declaring their variables are indexed much faster, with the work spread across every core.
- Long scripts and large classes. A long file of t
- Unreachable code is dimmed. Code that can never run, such as statements after a
- 0.11.02026-10-06 · 2026-10-06 01:12 UTC
查看更新说明
Highlights
New command-line tools
phpantom_lsp formatformats a whole project's PHP and Blade files with the same formatter your editor uses.--checkmakes it a CI gate.phpantom_lsp movemoves a class or a whole namespace. It updates declarations, imports, references, and PSR-4 paths, and lists any leftover mentions it couldn't rewrite. (@calebdw)analyzeaccepts multiple paths, so a pre-commit hook can pass only the files that changed.phpantom_lsp initis interactive. It asks about the settings people change most often and writes a.phpantom.tomlwith only what you changed.
New editor features
- Call hierarchy. See who calls a function or method, and what it calls. (@sidux)
- Reference and implementation CodeLens. Clickable counts above declarations open the references or implementations list. (@sidux)
- Convert qualified names to imports, for one name or for a whole namespace at once, with aliases added automatically when names collide. (@calebdw)
- Navigate to PHP classes from YAML and XML files. Ctrl+Click a class name or
Class::memberin config files to open it. (@sidux) - PHPUnit data providers and
@dependsare navigable. Renaming a provider method also updates the attributes and annotations that point to it. - PHPMD integration. Mess Detector findings appear in the editor using your project's existing config.
Blade
- Blade templates can be formatted. Optionally the PHP inside them is formatted too, and Pint is used if your project relies on it.
- Document outline and folding for
.blade.phpfiles. - Custom directives registered with
Blade::directive()/Blade::if()are recognised. - "Create missing view" quick fix.
- Diagnostics for unbalanced component tags.
- Named slots are scoped correctly, and anonymous components without
@propsget attribute completion.
Laravel
builder-of,collection-of,factory-of, andrelation-ofPHPDoc types resolve to the model's real Eloquent classes, including custom builders and dotted relation paths. They also work insideClosure(…)parameter types. (@calebdw)view-stringparameters complete template names and report unknown views. (@calebdw)- Storage disks and other configured service names (log channels, cache stores, auth guards, and more) get completion, hover, go-to-definition, references, and typo diagnostics. (@shuvroroy)
- UUID/ULID primary keys are typed as
string. (@shuvroroy) - Custom pivot accessors (
->as('participation')) are understood. (@shuvroroy, #381)
Configuration and indexing
- Exclude paths and add PHP file extensions with
[indexing]in.phpantom.toml, for example Drupal's.moduleand.inc. (@syntlyx) - VS Code and Cursor users get this automatically from
files.excludeandfiles.associations, and changes apply without a restart. - Symlinked directories are indexed with the rest of the project. (@liudashuang, #383)
- Nullable-only argument mismatches can be downgraded to warnings. (@iz-ahmad)
Performance
- Find References and the reference CodeLens are much faster on large projects. Searches run in parallel, skip files that can't match, and reuse earlier results. Opening a large Laravel controller went from about 13 s of background work to well under a second on repeat visits.
- Hover and completion no longer slow down in long functions with many local variables (4.3 s → 0.8 s on one test file).
- Analysis of very large files is faster (2.1 s → 0.7 s on php-parser's generated parser).
- Editing a file and searching for workspace symbols do much less work.
Other
- New
semantic-exportlibrary feature for headless tools that need declarations, references, and diagnostics without running an LSP. (@aaaaaandrew) - Bundled mago toolchain updated to 1.47.5. (@nguyentranchung)
- Extract interface is only offered in editors that can cre
- 0.10.02026-08-20 · 2026-08-20 01:22 UTC
查看更新说明
What's Changed
Added
Whole-project analysis
- Full workspace indexing. PHPantom now parses every PHP file in your project in the background after startup by default, building complete symbol data and a cross-file reference index. Find References, Rename, Go to Implementation, and Type Hierarchy resolve against the whole project instead of only the files you have opened, and scan only the files known to reference the symbol. Lighter modes remain available for projects that prefer a smaller footprint. Contributed by @sidux in https://github.com/PHPantom-dev/phpantom_lsp/pull/186.
- Workspace-wide diagnostics. Problems can now be surfaced across the whole project rather than only in open files. Set
workspace = trueunder[diagnostics]in.phpantom.tomland, once startup and the background index finish, diagnostics run over every file and stream into the editor's problems panel as they are found, so issues in files you have not opened are already visible when you navigate to them. Configured external tools (PHPStan, PHPCS, Mago) also run once over the whole project afterwards. Both passes are deferred until after startup so they never slow down the time it takes the editor to become usable. It is off by default: a project-wide sweep is real work on every session, and it is worth asking for rather than paying for unasked.
Blade templates
- A Blade template's variables come from a declared priority chain. What a template has in scope is now resolved rather than guessed at. A
@bladestan-signaturedocblock is the template's contract;@propsand@awarefill in what it leaves out; a component's own class, and Livewire's$this, supply their members;View::share()andView::composer()registrations in your service providers are read wherever they are written; a layout's declarations reach every template that extends it; and anything still undeclared is inferred from the call sites that render the template. Completion, hover, go-to-definition, and undefined-variable diagnostics all read the same set, alongside the variables Blade itself injects ($attributes,$slot,$componentName,$errors,$loop). Each source only fills in what the ones above it did not declare, so a template that documents its own contract keeps it. Closes #296. - Every way of rendering a Blade template is a render site.
view(),View::make(),Route::view(),Response::view(), the view factory'sfirst(),renderWhen(),renderUnless(), andrenderEach(), a mailable'snew Content(view: …)and$this->view(), and Blade's own@includefamily,@extends, and@eachall navigate, hover, complete, and hand the template the data they pass. A render is recognised by its receiver's type rather than by how it is spelled, so a view factory injected into a constructor and a mailable held in a local count too, and a data argument that names nothing (view('page', $data),->with($extra),array_merge(…)) is read off its type when that type is a single array shape. Contributed by @shuvroroy (#337). - A
view()call is checked against the Blade template's contract. A template that declares what it needs now holds its callers to it, the same way a function call is held to a signature: a variable the render does not pass, one whose type the declaration does not accept, and a key nothing in the template reads are each reported where the mistake is. This is the editor half of the rule Bladestan (the PHPStan extension for Blade) enforces in CI, so one annotation produces the same errors live while typing and on the build. A template that declares nothing is not checked at all, which is what makes this opt-in, and the checks stand down wherever the data stops being readable. A declaration that widens what its layout declared is reported on the template that writes it rather than at every call site. - Blade components are first-class.
<x-alert>,<x-forms.date-picker>, and `<livewir
- 0.9.02026-07-19 · 2026-07-19 23:24 UTC
查看更新说明
Added
- Macro hover shows origin and inferred return types. Hovering on a macro method call now displays a "macro" indicator instead of the generic "virtual" label, distinguishing
::macro()registrations from@method/@mixinsynthesized members. When the closure has no explicit return type hint, the return type is inferred from the closure body and shown with an "(inferred)" annotation. Bare$this/self/staticreturns preserve their keyword form, and method chains like$this->transform(...)use the last method's declared return type directly, preserving$this,static, and generic parameters that the general resolver would flatten to a bare class name. Regular (non-macro) methods with inferred return types also show the "(inferred)" annotation on hover. Contributed by @calebdw. - Return type mismatch diagnostics (
type_mismatch_return). Functions and methods with a declared return type are now checked against theirreturnstatements. Incompatible return values are flagged as errors. Void functions returning a value and barereturn;in non-void functions are also flagged. Generators (functions usingyield) are skipped. Uses the same conservativeis_type_compatiblepolicy as argument type checking to avoid false positives. Contributed by @calebdw. - Property type assignment diagnostics (
type_mismatch_property). Assignments to typed properties ($this->prop = exprandself::$prop = expr) are checked against the declared property type. Incompatible values are flagged as errors. Only plain=assignments are checked; compound operators (+=,.=, etc.) are skipped. Untyped andmixedproperties are not flagged. Contributed by @calebdw. - Conditional return types keep an intersection with the matched class. A
@return ($x is class-string<T> ? T&SomeInterface : SomeInterface)annotation now resolves the matched branch to the concrete class intersected with the interface, instead of collapsing it to the bare class. Mock factories such as Mockery'smock(Foo::class)and Laravel's$this->mock(Foo::class)therefore resolve toFoo&MockInterface, so their members complete and assigning the result to aFoo-typed property or returning it from aFoo&MockInterfacemethod no longer reports a spurious type mismatch. - PSR-4 mismatch diagnostics and rename-based moves. Files now warn when the declared namespace or primary class name does not match the PSR-4 path or filename, with quick fixes to correct them. Renaming a class from its declaration now opens the full FQCN so you can move it between namespaces in one step, and renaming a namespace can rewrite multiple segments at once while moving PSR-4 directories and updating references across the project. Contributed by @calebdw.
- Case-sensitive autoloading diagnostic. A class reference whose casing differs from the class's actual declaration is now flagged, with a quick fix to correct it. This catches the bug where code loads on a case-insensitive filesystem (macOS, Windows) but fails with a class-not-found error on Linux, because PSR-4 maps the name to a file path and path lookups are case-sensitive there. It covers
useimports and inline references to autoloaded classes; built-in classes and same-file references, which never reach the autoloader, are left alone. - Completion candidates ranked by dependency provenance. Class, function, and constant completions are now sorted by origin tier: project code first, then core/stub symbols, then explicit Composer dependencies (
require/require-dev), then transitive vendor dependencies last. The provenance is inferred fromcomposer.jsonandinstalled.jsonduring indexing. Contributed by @calebdw. analyzeandfixwork without composer.json. Both commands now treat a directory that has no composer.json (a WordPress site, a legacy codebase) as a plain PHP project: classes are indexed by scanning the tree and files are discovered by walking the roo
- Macro hover shows origin and inferred return types. Hovering on a macro method call now displays a "macro" indicator instead of the generic "virtual" label, distinguishing
- 0.8.02026-05-14 · 2026-05-14 12:23 UTC
查看更新说明
Added
- Blade template support. Completion, hover, go-to-definition, diagnostics, semantic tokens, and inlay hints work inside
.blade.phpfiles. Contributed by @MingJen in https://github.com/AJenbo/phpantom_lsp/pull/100. - Blade keyword highlighting. Blade directives, echo delimiters, PHP keywords, cast types, comments, and PHPDoc tags inside
.blade.phpfiles now receive semantic tokens for proper syntax coloring. - Blade view directive navigation. Go-to-definition works on view names inside Blade directives (
@include,@extends,@includeIf,@includeWhen,@includeUnless,@includeFirst,@component,@each), jumping to the referenced template file. - Replace FQCN with import. A refactoring code action on any fully-qualified class name (
\Foo\Bar) inserts ausestatement and replaces all occurrences of the same FQCN throughout the file with the short name. Detects existing imports and short-name conflicts. A separate "Replace all FQCNs with imports" action appears when the file contains multiple distinct FQCNs, replacing all of them at once (skipping those with import conflicts). - Broader type narrowing.
instanceof, type-guard functions,in_array()strict mode,assert(),@phpstan-assert-if-true/-if-false, and compound&&/||conditions now narrow types in if/else branches, guard clauses, while-loop bodies, ternary expressions, andmatch(true)arms. - Argument type mismatch diagnostics. Flags function and method calls where an argument's resolved type is incompatible with the declared parameter type.
- Invalid class-like kind diagnostics. Flags class-like names used in positions where their kind is guaranteed to fail at runtime:
newon abstract classes, interfaces, traits, or enums;extendson a final class, interface, or trait;implementswith a non-interface; traitusewith a non-trait;instanceofwith a trait;catchwith a non-Throwable type; and traits in type-hint positions. - Unused variable diagnostics. Variables assigned but never read are flagged with hint severity and rendered as dimmed text. Variables named
$_or prefixed with$_are exempt. - Mago diagnostic proxy. Mago lint and analyze diagnostics are surfaced as LSP diagnostics with quick-fix code actions. Configurable under
[mago]in.phpantom.toml. - Laravel Pint formatting. Projects with
laravel/pintinrequire-devautomatically use Pint for formatting via stdin. Configurable under[formatting]in.phpantom.tomlwithpint = "path"orpint = ""to disable. - PHPCS diagnostic proxy. PHP_CodeSniffer violations are surfaced as LSP diagnostics with severity mapping. Configurable under
[phpcs]in.phpantom.toml. - Return type inference from method bodies. Methods without a declared return type or
@returndocblock now have their return type inferred fromreturnstatements, improving completion, hover, and diagnostics for untyped code. - Closure and arrow function parameter inference. Untyped closure parameters are inferred from the enclosing call's callable signature, including through method chains that return
static. Generic type substitution flows through to inferred parameters. - Closure and arrow function inlay hints. When a closure or arrow function is passed to a callable-typed parameter, inlay hints show inferred parameter types and the return type derived from the enclosing callable signature.
- Generics.
@mixintags referencing a template parameter now resolve through the template bound.new $var()where$varisclass-string<T>resolves toT. SPL collection classes now carry@templateparameters so iteration methods resolve to concrete type arguments. - Namespace renaming. Renaming a namespace segment updates all declarations, use statements, and fully-qualified references across the workspace. When a PSR-4 autoload mapping exists, the corresponding directory is moved automatically.
-
- Blade template support. Completion, hover, go-to-definition, diagnostics, semantic tokens, and inlay hints work inside
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
PHPantom
A fast, lightweight PHP language server written in Rust. Ready in seconds, keeps memory use modest even on large codebases, and stays responsive throughout. Indexing happens in the background, so you're never left waiting on it.
Check out the documentation to get started.
Features
PHPantom focuses on deep type intelligence. Here's how it compares:
| PHPantom | Intelephense | PHP Tools | Phpactor | PHPStorm | |
|---|---|---|---|---|---|
| Core LSP features1 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Advanced navigation2 | ✅ | 🚧🔒 | 🚧 | 🚧 | ✅ |
| Editor extras3 | ✅ | 🚧🔒 | 🚧 | 🚧 | ✅ |
| Diagnostics | |||||
| Built-in diagnostics4 | ✅ | 🚧🔒 | ✅ | 🚧 | ✅ |
| External analyzer integration5 | ✅ | ❌ | ❌ | 🚧 | 🚧 |
| Type Intelligence | |||||
Generics / @template | ✅ | 🚧 | ✅ | 🚧 | 🚧 |
| Array / object shapes | ✅ | ✅ | ✅ | 🚧 | 🚧 |
| Advanced PHPDoc types6 | ✅ | 🚧🔒 | 🚧 | 🚧 | 🚧 |
| Closure parameter inference | ✅ | 🚧 | 🚧 | 🚧 | 🚧 |
| Frameworks | |||||
| Laravel & Blade | ✅ | ❌ | 🚧 | ❌ | 🚧🧩 |
| Symfony & Twig | ✅ | ❌ | ❌ | 🚧 | 🧩 |
| WordPress | ✅ | 🚧 | 🚧 | ❌ | ✅ |
| Drupal | ✅ | ❌ | ❌ | ❌ | ✅🧩 |
| Yii 3 | ✅ | ❌ | ❌ | ❌ | 🚧🧩🔒 |
| Tempest | 🚧 | ❌ | ❌ | ❌ | 🧩 |
| PHPUnit & Pest | ✅ | ❌ | 🚧 | 🚧 | ✅ |
| Other frameworks | ❌ | 🚧 | 🚧 | 🚧 | 🧩 |
| Refactoring | |||||
| Rename | ✅ | ✅🔒 | ✅ | ✅ | ✅ |
| Extract & generate8 | ✅ | ❌ | 🚧🔒 | 🚧 | ✅ |
| Simplify & modernize9 | ✅ | ❌ | ✅🔒 | ❌ | ✅ |
| Performance | |||||
| Time to ready (from cache) | 2 s | 11 s (1 s) | 10 s | 1 min 34 s (4 s) | 1 min 7 s (5 s) |
| RAM | 578 MB | 766 MB | 594 MB | 467 MB | 2 GB |
| CPU time | 17 s | 16 s | 36 s | 5 min 33 s | 17 min 55 s |
| Disk cache | - | 51 MB | - | 2.3 GB | 379 MB |
[!TIP] Want to verify? Open
examples/php/in your editor and trigger completion at the marked locations incompletion.php. It exercises every type intelligence feature in the table, including edge cases where tools diverge. Each framework has a standalone project of its own, with a README listing what to try:examples/laravel/,examples/symfony/,examples/wordpress/,examples/yii/, andexamples/tempest/.
Context-Aware Intelligence
- Smart PHPDoc completion.
@throwsdetects uncaught exceptions in the method body,@parampre-fills from the signature, and tags are filtered to context and never suggested twice. - Array shape inference. Literal arrays offer key completion with no annotation. Nested shapes, spreads, and array functions like
array_mappreserve element types. - Closure parameter inference.
$users->map(fn($u) => $u->name)infers$uasUserfrom the collection's generic context. - Conditional return types. PHPStan-style conditional
@returntypes resolve to the concrete branch at each call site. - Type aliases and shapes.
@phpstan-type,@phpstan-import-type, andobject{...}shapes all resolve through to completions. - The full modern language. PHP 8.4 and 8.5 features resolve end-to-end: property hooks, asymmetric visibility, and the pipe operator behave like any other code.
- Laravel. Eloquent relationships, scopes, accessors, casts, and Builder chains resolve end-to-end. Macros behave like real methods. Container strings like
app('cache')resolve to the bound class,auth()->user()resolves to your configured model, authorization strings resolve to the gate definition or policy method that declares them, and query string completion on both relation and column names. Blade templates get completion, hover, go-to-definition, and diagnostics through virtual PHP preprocessing, and Livewire components and Folio pages are understood alongside them. No ide-helper or database access required. - Symfony. The names Symfony takes as strings complete, navigate, and list their references across PHP, YAML, XML, and Twig, and the ones nothing declares are reported. Form fields and validation mappings resolve to the properties they name. Doctrine entities and repositories link to each other, and renames reach the mapping files. Everything is read from the project's files, without booting the application.
- Twig. Template names complete, navigate, and are checked in any project that uses Twig, Symfony or not. Blocks navigate between the templates that override them, filters and functions lead to the PHP that runs them, with its signature on hover, and variables lead to the renders and templates that pass them and hold what those pass, so
post.completes and navigates the entity's attributes. The template directories are found from the templates themselves, with no configuration. - WordPress. Core's functions and classes come from
php-stubs/wordpress-stubsonce Composer installs it, and their return types follow the arguments. Hook names, core's included, complete and navigate between the places that fire a hook and the ones that listen to it, and the project's own rename.@globaltags type the globals a function imports. - Yii 3. Route names, route arguments, and view names complete, navigate, and are checked, and a route's handler renames with the method it names. Everything is read from the application's configuration without booting it.
- Tempest. View templates get completion, hover, go-to-definition, and diagnostics through virtual PHP, the same way Blade templates do. The data a view is rendered with is typed from the calls and View objects that render it, and component attributes and slots get the scope Tempest renders them in. Component tags and their attributes complete and navigate, and the paths passed to
view()complete and lead to their templates. - Testing. PHPUnit's assertions narrow types, in Pest tests too. Test metadata (data providers, dependencies, coverage) navigates and renames, a class links to its tests and each test back to the class it tests, a class without a test gets one created in the right place, and mocks keep the mocked class, with the methods an expectation names completing, navigating, and renaming like calls. Inside a Pest test,
$thisis the test case yourPest.phpbinds. - Everything else you'd expect. Generics, type narrowing, named arguments, destructuring, first-class callables, anonymous classes,
@deprecateddetection, and namespace segment drilling.
Project Awareness
PHPantom understands Composer projects out of the box, but works without setup on non-Composer projects too:
- Frameworks need no setup. Laravel, Symfony, WordPress, Drupal, Yii, Tempest, PHPUnit, and Pest are recognised from the project itself, and their code is read from where the project already has it. There is nothing to enable, download, or point at.
- Autoloader-accurate results. Completions and go-to-definition only surface classes that Composer's autoloader can actually load, avoiding false positives from internal, inaccessible, or duplicate vendor classes. You see exactly what your application can use.
- PSR-4 correctness. Quick fixes for when the namespace or class name does not match their PSR-4 path.
- PSR-4 autoloading. Resolves classes across files on demand.
- Classmap and file autoloading.
autoload_classmap.phpandautoload_files.php. - Embedded PHP stubs from phpstorm-stubs bundled in the binary, no runtime downloads needed.
- Drupal project support. Detects Drupal projects, with or without a
composer.json, resolves the web root, and indexes Drupal-specific directories and PHP extensions (.module,.install,.theme, etc.) with.gitignorebypassed so that Composer-managed core and contrib code is always available. require_oncediscovery. Functions from required files are available for completion.- Go-to-implementation. Jump from an interface or abstract class to all concrete implementations. Scans open files, classmap, PSR-4 directories, and embedded stubs.
- Go-to-declaration. Jump from a method call or a method to the interface or abstract method it implements.
- Workspace-wide diagnostics. After startup, diagnostics run in the background across every file in the project, not just the ones you have open, so problems are already visible when you navigate to a file. Configured external tools (PHPStan, PHPCS, PHPMD, Mago) run project-wide too, once the background pass finishes. Both are deferred until after startup so they never slow down time to ready.
Acknowledgements
PHPantom stands on the shoulders of:
- Mago: the PHP parser that powers all of PHPantom's AST analysis.
- PHPStan and Psalm: for their pioneering work in PHP static analysis and shaping the type ecosystem. PHPantom builds on PHPStan-informed type experience, with full support for
@phpstan-*annotations. - JetBrains phpstorm-stubs: type information for the entire PHP standard library, embedded directly into the binary.
- Viktor Szépe (@szepeviktor): for wordpress-stubs, which supplies PHPantom's knowledge of WordPress core, and phpstan-wordpress, whose return-type rules and test fixtures shaped PHPantom's WordPress support.
- Phpactor: the PHP language server whose comprehensive test suite and benchmark fixtures informed PHPantom's own test coverage. Many of PHPantom's type inference fixtures were adapted from Phpactor's reflection tests.
License
MIT. See LICENSE.