PHPackages                             good-php/reflection - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. good-php/reflection

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

good-php/reflection
===================

Reflection API with a type system, generics support and cache

v2.5.1(8mo ago)525.4k↓35.7%[6 issues](https://github.com/good-php/reflection/issues)1MITPHPPHP &gt;=8.2CI passing

Since Nov 3Pushed 7mo ago3 watchersCompare

[ Source](https://github.com/good-php/reflection)[ Packagist](https://packagist.org/packages/good-php/reflection)[ RSS](/packages/good-php-reflection/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (18)Versions (21)Used By (1)

Good PHP reflection
===================

[](#good-php-reflection)

Reflection that accounts for features that are in static analysers, but aren't in the language yet.

```
$reflector = new ReflectorBuilder()
	->withFileCache()
	->withMemoryCache()
	->build();

// Reflect a Collection class with generic types: Collection
$reflection = $reflector->forType(\Illuminate\Support\Collection::class, [
	PrimitiveType::integer(), // TKey
	\DateTime::class, // TValue
]);

// array
$reflection->property('items')->type();

// \DateTime
$reflection->method('prepend')->parameter('value')->type();

// \Traversable
$reflection->method('getIterator')->returnType();
```

### 🙋 Who is it for?

[](#-who-is-it-for)

If you've used reflection and missed having PHPDoc-parsed types and other information - this is for you.

### 🤔 Why?

[](#-why)

PHP is in a state where some very vital features only exist in userland (i.e. PHPStan), like generics, tuple types, conditional types, type aliases and more. When you need reflection, you usually also need it to work with all of those userland features. Obviously, PHP's built in reflection doesn't do that.

### ⚡ Can I use it in runtime?

[](#-can-i-use-it-in-runtime)

Yes! That's the point - you can and should use it in runtime.

- need to reflect properties of a class for serialization? Done.
- need to reflect constructor parameters for dependency injection? Done.
- need to reflect methods of a class for an auto-mapped HTTP client? Done.

It uses some clever caching and does a lot of computations lazily. While the performance is worse than the native reflection, it is still much better than the alternatives, and is definitely quick enough for runtime. See benchmarks below.

### 🛠️ What features are supported?

[](#️-what-features-are-supported)

Here are some of the features supported:

- 🟢 Reflection for classes, traits, interfaces and enums
- 🟢 Generics (reflect and substitute)
- 🟢 Tuple types
- 🟢 Anonymous classes
- 🟢 Blazing fast cache
- 🔴 Support for `strict_types` configurations
- 🔴 Conditional types
- 🔴 Type aliases
- 🔴 Template type inference for functions

### 🐞 How reliable is this?

[](#-how-reliable-is-this)

It's been used in production by a large project for some time. It's somewhat stable.

To avoid as much problems as possible, we aim for:

- phpstan `max` level with as little ignored errors as possible
- 90% tests coverage

That said, due to the dynamic nature of PHPDoc and complex type system it provides, it's expected to encounter bugs and problems.

### 🚀 How fast is this?

[](#-how-fast-is-this)

Pretty fast - in range of nanoseconds with warm cache. Here is a reference benchmark, performed on an M1 MacBook Pro with OpCache and JIT:

[![benchmark](./benchmark/result/screenshot.png)](./benchmark/result/screenshot.png)

It's obviously not the fastest, but it down to nanoseconds with cache, and it does more than it's contenders :)

There's one other alternative I'm aware of - `typhoon-php/reflection`. Here is a separate benchmark for it (I couldn't generate it in the same graph because of dependency mismatch):

[![typhoon benchmark](./benchmark/typhoon/result/screenshot.png)](./benchmark/typhoon/result/screenshot.png)

It's a bit slower, but still plenty fast.

### 🚫 What not to expect?

[](#-what-not-to-expect)

Unlikely to have support:

- "static" reflection (not executing PHP files that are being reflected)
- reflecting non-PHP or invalid PHP files

Unfortunately these creep into the territory of `roave/better-reflection`, which is just way too slow for runtime use.

### 🔍 Why not just use `roave/better-reflection` or similar?

[](#-why-not-just-use-roavebetter-reflection-or-similar)

While custom reflection libraries do exist (like `roave/better-reflection`), they generally aren't suitable for runtime use. That is, they're great at providing a lot of information, but they're also resource-hungry and quite slow - because they were created for a different purpose.

Additionally, many don't provide a type system or nice APIs - they generally built upon PHP's native reflection, but that doesn't play well with PHPDoc types.

### 📦 What about `phpstan`'s reflection?

[](#-what-about-phpstans-reflection)

The perfect scenario here would be for PHPStan to simply extract it's own reflection into a package, but this has already [been declined](https://github.com/phpstan/phpstan/discussions/4646)by the project author @ondrejmirtes, and understandably so. I've tried extracting it myself by relocating parts of the PHPStan code, but it has proven to be complex, unreliable and most importantly - slow to execute.

So instead this projects attempts to fill the holes of the native reflection and modernize the API in the process. Most of the API is defined with interfaces which you can extend to implement things you need done.

### ⚙️ How does it work internally?

[](#️-how-does-it-work-internally)

Unfortunately, it's not as simple as just using the native reflection and parsing some PHPDocs on the side. Although PHP's Reflection is quite powerful, it doesn't provide all the tools necessary to efficiently parse PHPDoc. Namely, there are a few limitations:

- you can't access `use` statements (imports), needed to map "imported" classes in PHPDocs
- you can't reliably access "immediate" (i.e. declared within that structure) interfaces, trait uses, constants, properties and methods - all needed for nested generic types
- you can't access trait use docblocks, aliases or precedence - all needed for generics

Because of these limitations we have to rely on a mix of native reflection and AST parsing. The general principle is this: collect as many bits of information from the native reflection (because it's the fastest and most reliable) and some additional information from parsing PHP files with `nikic/php-parser`, then combine them together, producing a "definition".

A "definition" is a term we use to denote a data-only class that holds reflection information of a specific structure (i.e. it's generic type parameters, properties, methods etc), but only of that specific structure (excluding inherited ones). This is done for a couple of reasons, but the primary one is generics: this way it's easy to substitute them in the entire inheritance tree by recursively mapping them to each supertype.

There are also definition *providers* which do exactly what they sound. You can chain as many of them as you like and provide/override the reflection data with any source. By default, it uses native reflection and `phpstan/phpdoc-parser` to gather all of the information, but you can adapt any other reflection library as you wish.

Reflection, on the other hand, is the user-facing API. Instead of collecting the reflection data, it simply "presents" the definition-provided one with a set of APIs:

- meant for end-user
- fully fledged API
- untrivial to serialize/cache because of dependencies (such as Reflector)

Such approach allows to have a clear separation between cacheable data structures and the reflection itself, which depends on the `Reflector` instance.

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance42

Moderate activity, may be stable

Popularity32

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 75% 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

Every ~40 days

Recently: every ~0 days

Total

18

Last Release

244d ago

Major Versions

v1.0.2 → v2.0.02025-07-08

PHP version history (2 changes)v1.0.0-alpha.1PHP &gt;=8.1

v1.0.0-alpha.3PHP &gt;=8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/10583125?v=4)[Oleksandr Prypkhan](/maintainers/autaut03)[@autaut03](https://github.com/autaut03)

---

Top Contributors

[![autaut03](https://avatars.githubusercontent.com/u/10583125?v=4)](https://github.com/autaut03 "autaut03 (57 commits)")[![semantic-release-bot](https://avatars.githubusercontent.com/u/32174276?v=4)](https://github.com/semantic-release-bot "semantic-release-bot (19 commits)")

---

Tags

meta-programmingphpreflection

###  Code Quality

TestsPest

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/good-php-reflection/health.svg)

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

###  Alternatives

[phpdocumentor/reflection-docblock

With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.

9.4k722.2M1.2k](/packages/phpdocumentor-reflection-docblock)[icanhazstring/composer-unused

Show unused packages by scanning your code

1.7k7.0M188](/packages/icanhazstring-composer-unused)[psalm/plugin-laravel

Psalm plugin for Laravel

3274.9M308](/packages/psalm-plugin-laravel)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[tempest/framework

The PHP framework that gets out of your way.

2.1k23.1k9](/packages/tempest-framework)[bakame/laravel-domain-parser

Laravel package to integrate PHP Domain parser.

26534.8k4](/packages/bakame-laravel-domain-parser)

PHPackages © 2026

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