Skip to content

About

Fast PHP language server with deep type intelligence. Generics, Laravel, PHPStan annotations. Ready in an instant.

Topics

Resources

Contributing

Stars

1.3k stars

Watchers

9 watching

Forks

Repository files navigation

PHPantom

Spookaphant
CI codecov crates

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 ✅ 🚧 🚧 ❌ ✅
Yii 3 ✅ ❌ ❌ ❌ ❌
Drupal 🚧 ❌ ❌ ❌ ✅🧩
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

🚧 = partial support. ❌ = not available. 🧩 = via plugin. 🔒 = paid tier.
1 Completion, hover, signature help, go-to-definition, find references, diagnostics, document symbols, workspace symbols.
2 Call hierarchy, type hierarchy, go-to implementation / type-definition, code lens.
3 Semantic tokens, inlay hints, auto-import, smart select, folding ranges, formatting, document links.
4 Undefined and unused variables, type errors, unknown symbols and members, argument counts.
5 PHPStan, PHPCS, PHPMD, and Mago run in-server, and their reports come with quick fixes rather than as relayed errors.
6 Conditional return types, type aliases, pseudo-types, `@mixin`.
8 Extract and inline, generate constructors and accessors, implement interfaces.
9 Rewrites to modern syntax, such as `match`, arrow functions, and simpler null checks.
Performance measured on a production Laravel codebase: 5.1K PHP files (389k lines) and 1.3K Blade templates (88k lines), with 27k vendor files (1.7M lines). Time to ready is the approximate wall-clock time from launch until full type intelligence is available on a cold start (first index). RAM is the steady resident memory once indexing has finished.
Independent, re-runnable type-inference conformance results across twelve PHP engines: php-typing-conformance (Qodana covers the PHPStorm engine, phpy the PHP Tools engine).

Tip

Want to verify? Open examples/php/ in your editor and trigger completion at the marked locations in completion.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/, and examples/yii/.

Context-Aware Intelligence

  • Smart PHPDoc completion. @throws detects uncaught exceptions in the method body, @param pre-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_map preserve element types.
  • Closure parameter inference. $users->map(fn($u) => $u->name) infers $u as User from the collection's generic context.
  • Conditional return types. PHPStan-style conditional @return types resolve to the concrete branch at each call site.
  • Type aliases and shapes. @phpstan-type, @phpstan-import-type, and object{...} 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-stubs once 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. @global tags 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.
  • 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, $this is the test case your Pest.php binds.
  • Everything else you'd expect. Generics, type narrowing, named arguments, destructuring, first-class callables, anonymous classes, @deprecated detection, and namespace segment drilling.

Project Awareness

PHPantom understands Composer projects out of the box, but works without setup on non-Composer projects too:

  • 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.php and autoload_files.php.
  • Embedded PHP stubs from phpstorm-stubs bundled in the binary, no runtime downloads needed.
  • Drupal project support. Detects Drupal projects via composer.json, resolves the web root, and indexes Drupal-specific directories and PHP extensions (.module, .install, .theme, etc.) with .gitignore bypassed so that Composer-managed core and contrib code is always available.
  • require_once discovery. 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.
  • 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.

About

Fast PHP language server with deep type intelligence. Generics, Laravel, PHPStan annotations. Ready in an instant.

Topics

Resources

Contributing

Stars

1.3k stars

Watchers

9 watching

Forks

Releases

Contributors

Languages