# BetterReflection: A Reflection API for PHP Static Analysis Tools

> Better Reflection is a PHP library that reflects on code without loading it, on classes given as a string, on closures and on the abstract syntax tree of a method body, and it is aimed squarely at static analysis tooling rather than runtime use. The library warns that its performance is much worse than PHP's built-in reflection, and says the Better in the name refers to features, not speed.

**Roave/BetterReflection** — :crystal_ball: Better Reflection is a reflection API that aims to improve and provide more features than PHP's built-in reflection API.

- Repository: https://github.com/Roave/BetterReflection
- Stars: 1,249 · Forks: 138
- Language: PHP
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/roave-betterreflection

## Reflection That Does Not Need the Class Loaded

Better Reflection is described as a reflection API that aims to improve and provide more features than PHP's built-in reflection API, and the first feature on the list is the one that changes how you can use it: you can reflect on classes that are not already loaded, without loading them.

That is the conceptual difference. PHP's own reflection works on what the runtime has already brought into memory, which means the class has to be autoloadable and the autoloader has to succeed, and any side effect of loading the file has already happened by the time you ask a question about it. Better Reflection works from the source, so a tool can ask what a class looks like in a directory of files without executing a single line of that code.

The second entry in the list follows from the first: the ability to reflect on classes directly from a string of PHP code. A tool that receives a snippet, or that needs to analyse code which is not on the include path at all, can still reflect on it.

The rest of the list is the feature surface, and it is worth reading as a description of what a static analyser needs: reflecting directly on closures, extracting the AST from methods and functions, returning the AST representation of a class or function, and fetching return type and parameter type declarations in PHP 7 code.

The AST entries are what make this more than a reflection API. A doc block tool wants types; a code transformation tool wants the tree the code came from.

## The Typical Use Is a Static Analysis Baseline

The README is direct about what the library is for. Typically you would use Better Reflection for static analysis tooling, and it can serve as a baseline to access type information, for example doc blocks and type declarations, and method and function body AST fetching, for static analysis.

The word baseline is doing the work there. A static analyser needs a picture of the program that does not depend on running the program, and building that picture from PHP's own reflection is impossible for the cases the library covers. So Better Reflection is the layer that sits underneath tools rather than a tool itself.

The documentation set matches that role. There is a page on compatibility with the core Reflection API, basic usage instructions, a page on using types, a page on the features, and a separate test suite documentation. The compatibility page is the interesting one for an adopter, because it is the contract that tells you which parts of the built-in API the library mirrors and which it does not.

The demos in the repository follow the same pattern, with a basic reflection demo and a demo that parses a whole directory, which is the case the library exists to serve.

## The Warning: It Is Not for Runtime Use

The README spends a paragraph on this, and it is the first thing to internalise.

Better Reflection is NOT suited to runtime usage, since performance is much worse than PHP built-in reflection. If you do not want to do anything that native PHP reflection cannot do, then just use native PHP reflection. The Better in Better Reflection refers to feature, not speed.

That last sentence is a good summary of the library's position, and it explains why the project would rather you not use it. A tool that runs in a request path and reflects on a class for each call would be dramatically slower with this library, and the difference is not marginal.

The natural way to think about it is as an analysis-time library. It runs in a CI job, in an IDE indexer, in a code generation step, or in a test that inspects source rather than behaviour. In those places the cost is paid once per file rather than once per call, and the cost buys the features that native reflection cannot offer at all.

## Installing and the Three-Line Entry Point

The installation is a Composer requirement:

```shell
composer require roave/better-reflection
```

And the usage is short enough to show in full, which is a good sign for an API that is meant to be read:

```php
<?php

use Roave\BetterReflection\BetterReflection;

$classInfo = (new BetterReflection())
    ->reflector()
    ->reflectClass(\Foo\Bar\MyClass::class);
```

The shape is a factory that produces a reflector, and the reflector has a method per kind of thing you want to reflect on. That is the shape you would expect from a library whose job is to be called from many different tools, since the alternative would be a static helper or a global.

The package is published on Packagist as roave/better-reflection, and the repository also carries a demo directory with a basic reflection example and a whole directory parsing example, plus the CONTRIBUTING notes for anyone who wants to work on it.

## The Compatibility Contract and the Upgrade Document

Two documents matter to anyone adopting this, and the README points at both.

The first is the compatibility documentation, which covers compatibility with the core Reflection API. For a library that positions itself as a superset of a built-in API, the interesting question is not what it adds but whether the parts it mirrors behave the same way, and that is what the page is for. A tool written against native reflection can often be pointed at Better Reflection with small changes, and the compatibility page is where you find out which.

The second is UPGRADE.md, and the README asks you to refer to it to see what is required to upgrade your installed BetterReflection version. The project is on a 6.x line, with the default branch at 6.74.x and recent releases of 6.73.0 on 2026-09-09, 6.72.0 on 2026-07-22 and 6.71.0 on 2026-05-02. A library that releases this often and asks you to read an upgrade document is a library where breaking changes are part of the normal contract, which is worth knowing before you build a tool on it.

The three releases over five months also tell you the maintenance rate, and it is steady rather than sporadic, which is the pattern you want from a dependency that other tools are built on.

## The One Hard Limitation: Functions

The limitations section has a single entry, and it is a real one. PHP cannot autoload functions, therefore we cannot statically reflect functions.

The reason is a property of the language rather than of the library. A class is resolved by name through the autoloader, and the library can go and find that file itself, so it can read a class that has never been loaded. A function has no equivalent mechanism, so when the library wants to reflect on a function it has to find the file some other way, and the README says it cannot do that reliably.

For a static analyser, that is a meaningful hole. A file of procedural code with functions and no classes is a common shape, and code that calls a function defined in another file cannot be resolved by this library the way a class can. The workaround in practice is to give the analyser a set of source files to scan, which is what the demo that parses a whole directory is doing.

It is also worth being clear that the limitation is narrower than it first looks. A method is a function, but methods live in classes, so the class mechanism covers them, and the AST extraction feature works on methods and functions in the sense of the code you have already located.

## The Quality Tooling Around the Library

The repository carries an unusually complete static analysis setup, and for a library that other tools depend on, that is part of the product.

The badges tell part of the story. There is a mutation testing badge pointing at the Stryker mutator dashboard, a type coverage badge from shepherd.dev, and the Packagist badges for the latest stable version and the licence. Mutation testing is the interesting one, because it measures whether the test suite actually catches behaviour changes rather than just executing lines.

The configuration files show the rest. There is an infection.json.dist for the mutation testing run, a phpbench.json for the benchmarks, a phpcs.xml.dist for the coding standard, a phpstan.neon for static analysis, a phpunit.xml.dist for the tests, and psalm.xml with a psalm-baseline.xml beside it, which is the record of the issues Psalm currently accepts. Renovate is configured for dependency updates.

The src/ and test/ directories are the library and its suite, tools/ holds the supporting scripts, and docs/ holds the documentation pages the README links. The project is released under the MIT licence, the repository is not archived, and the last push was on 2026-10-15, so the code is current even as the release line moves.

## Conclusion

Better Reflection fits a team building a static analyser, a doc block tool, a code generator or a test that needs to know a method's signature and body without executing the class, since that is the whole reason the library exists. It is a poor fit for application runtime code, where the built-in reflection API is faster and sufficient, and the README says so plainly. Before adopting it, read the compatibility documentation, which maps the library onto the core reflection API, and read UPGRADE.md, since the project maintains a dedicated upgrade guide, and note the one hard limitation, that functions cannot be autoloaded by PHP and therefore cannot be reflected on statically. The library is MIT licensed, the current version line is 6.74.x, the newest release is 6.73.0 from 2026-09-09, and the last push was on 2026-10-15.

## FAQ

### What does Better Reflection add to PHP's built-in reflection?

You can reflect on classes that are not already loaded, without loading them, reflect on classes directly from a string of PHP code, reflect directly on closures, extract the AST from methods and functions, return the AST representation of a class or function, and fetch return type and parameter type declarations in PHP 7 code.

### Is Better Reflection suitable for runtime code?

No. The README states that it is NOT suited to runtime usage because performance is much worse than PHP's built-in reflection, and that if you do not want to do anything native PHP reflection cannot do, you should just use native PHP reflection. The Better refers to features, not speed.

### How do I install and use Better Reflection?

Require it with `composer require roave/better-reflection`, then create a BetterReflection instance, call reflector() on it and pass the class name to reflectClass(). The package is published on Packagist as roave/better-reflection.

### What are the limitations of Better Reflection?

PHP cannot autoload functions, therefore the library cannot statically reflect functions. Classes are resolved through the autoloader mechanism and can be reflected on without being loaded, but free functions are not.

### How is Better Reflection maintained and tested?

The repository carries a mutation testing setup through infection and the Stryker dashboard badge, a type coverage badge, and configuration for PHPUnit, PHPStan, Psalm with a baseline, PHP_CodeSniffer and phpbench, with Renovate handling dependency updates. The current line is 6.x and the last push was on 2026-10-15.

## Sources

- [Issues](https://github.com/Roave/BetterReflection/issues)
- [License: MIT](https://github.com/Roave/BetterReflection/blob/6.74.x/LICENSE)
- [README](https://github.com/Roave/BetterReflection/blob/6.74.x/README.md)
- [Releases](https://github.com/Roave/BetterReflection/releases)
- [Roave/BetterReflection on GitHub](https://github.com/Roave/BetterReflection)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/roave-betterreflection
