PHPackages                             bermudaphp/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. [Caching](/categories/caching)
4. /
5. bermudaphp/reflection

ActiveLibrary[Caching](/categories/caching)

bermudaphp/reflection
=====================

Powerful PHP reflection utility with caching and advanced metadata handling

v2.0(11mo ago)0422MITPHPPHP ^8.4CI passing

Since May 9Pushed 11mo ago1 watchersCompare

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

READMEChangelog (2)Dependencies (1)Versions (3)Used By (2)

Bermuda Reflection
==================

[](#bermuda-reflection)

**[Русская версия](README.RU.md)**

A powerful static utility class for PHP reflection operations with built-in caching and advanced metadata (attributes) handling. Provides convenient methods for working with PHP 8+ attributes and reflection objects.

Features
--------

[](#features)

- 🚀 **Performance Optimized**: Built-in caching for reflection objects
- 🎯 **Attribute Support**: Comprehensive PHP 8+ attributes handling
- 🔍 **Deep Search**: Search attributes in class members (methods, properties, constants)
- 🧩 **Universal Reflection**: Smart reflection creation from various data types
- 💾 **Memory Efficient**: Automatic caching prevents duplicate reflection objects
- 🔧 **Type Safe**: Full generic type support for attributes

Installation
------------

[](#installation)

```
composer require bermudaphp/reflection
```

Requirements
------------

[](#requirements)

- PHP 8.4 or higher

Quick Start
-----------

[](#quick-start)

### Basic Attribute Retrieval

[](#basic-attribute-retrieval)

```
use Bermuda\Reflection\Reflection;

class UserController
{
    #[Route('/api/users')]
    #[Auth('admin')]
    public function index(): Response
    {
        // method implementation
    }
}

$reflection = new ReflectionMethod(UserController::class, 'index');

// Get all attributes
$attributes = Reflection::getMetadata($reflection);

// Get specific attribute type
$routes = Reflection::getMetadata($reflection, Route::class);

// Get first attribute of specific type
$route = Reflection::getFirstMetadata($reflection, Route::class);

// Check if attribute exists
$hasAuth = Reflection::hasMetadata($reflection, Auth::class); // true
```

### Universal Reflection

[](#universal-reflection)

```
use Bermuda\Reflection\Reflection;

// Reflect different types automatically
$reflection = Reflection::reflect('MyClass');           // ReflectionClass
$reflection = Reflection::reflect($object);             // ReflectionObject
$reflection = Reflection::reflect('function_name');     // ReflectionFunction
$reflection = Reflection::reflect([$obj, 'method']);    // ReflectionMethod
$reflection = Reflection::reflect(fn() => true);       // ReflectionFunction
```

Advanced Features
-----------------

[](#advanced-features)

### Deep Attribute Search

[](#deep-attribute-search)

Search for attributes not only on the class itself, but also on all its members:

```
use Bermuda\Reflection\Reflection;

class UserService
{
    #[Inject]
    private UserRepository $repository;

    #[Route('/users')]
    #[Cache(ttl: 3600)]
    public function getUsers(): array
    {
        return $this->repository->findAll();
    }

    #[Deprecated('Use getUsers() instead')]
    public const OLD_ENDPOINT = '/api/users';
}

$reflection = new ReflectionClass(UserService::class);

// Get ALL attributes from class and its members
$allAttributes = Reflection::getDeepMetadata($reflection);
/*
Returns:
[
    'UserService::$repository' => [Inject],
    'UserService::getUsers' => [Route, Cache],
    'UserService::OLD_ENDPOINT' => [Deprecated]
]
*/

// Get specific attribute type from anywhere in the class
$injectAttributes = Reflection::getDeepMetadata($reflection, Inject::class);
/*
Returns:
[
    'UserService::$repository' => [Inject]
]
*/

// Get first occurrence of attribute in the class
$firstRoute = Reflection::getFirstDeepMetadata($reflection, Route::class);

// Check if class has attribute anywhere
$hasInject = Reflection::hasDeepMetadata($reflection, Inject::class); // true
```

### Path Format for Deep Search

[](#path-format-for-deep-search)

Deep search results use descriptive paths to identify where attributes were found:

- `ClassName` - Attribute on the class itself
- `ClassName::methodName` - Attribute on a method
- `ClassName::$propertyName` - Attribute on a property
- `ClassName::CONSTANT_NAME` - Attribute on a class constant

### Reflection Caching

[](#reflection-caching)

The class automatically caches reflection objects for improved performance:

```
use Bermuda\Reflection\Reflection;

// First call creates and caches ReflectionClass
$reflection1 = Reflection::class('MyClass');

// Second call returns cached instance (faster)
$reflection2 = Reflection::class('MyClass');

// $reflection1 === $reflection2 (same object)

// Manually add custom reflector to cache
Reflection::addReflector('my-key', $customReflector);
```

API Reference
-------------

[](#api-reference)

### Metadata Methods

[](#metadata-methods)

#### `getMetadata()`

[](#getmetadata)

```
public static function getMetadata(
    ReflectionFunctionAbstract|ReflectionClass|ReflectionParameter|ReflectionConstant $reflector,
    ?string $name = null
): ?array
```

Retrieves all attributes from a reflection object. Optionally filter by attribute class name.

```
$allAttributes = Reflection::getMetadata($reflection);
$routeAttributes = Reflection::getMetadata($reflection, Route::class);
```

#### `getFirstMetadata()`

[](#getfirstmetadata)

```
public static function getFirstMetadata(
    ReflectionFunctionAbstract|ReflectionClass|ReflectionParameter|ReflectionConstant|ReflectionProperty $reflector,
    string $name
): ?object
```

Gets the first attribute instance of the specified type.

```
$route = Reflection::getFirstMetadata($methodReflection, Route::class);
if ($route) {
    echo $route->path; // '/api/users'
}
```

#### `hasMetadata()`

[](#hasmetadata)

```
public static function hasMetadata(
    ReflectionFunctionAbstract|ReflectionClass|ReflectionParameter|ReflectionConstant|ReflectionProperty $reflector,
    string $name
): bool
```

Checks if the reflection object has any attributes of the specified type.

```
if (Reflection::hasMetadata($reflection, Cache::class)) {
    // Handle caching logic
}
```

### Deep Search Methods

[](#deep-search-methods)

#### `getDeepMetadata()`

[](#getdeepmetadata)

```
public static function getDeepMetadata(
    ReflectionClass $reflector,
    ?string $name = null
): array
```

Searches for attributes in the class and all its members (methods, properties, constants).

```
// Get all attributes from everywhere in the class
$allAttributes = Reflection::getDeepMetadata($classReflection);

// Get only Route attributes from anywhere in the class
$routes = Reflection::getDeepMetadata($classReflection, Route::class);
```

#### `getFirstDeepMetadata()`

[](#getfirstdeepmetadata)

```
public static function getFirstDeepMetadata(
    ReflectionClass $reflector,
    string $name
): ?object
```

Gets the first attribute instance found anywhere in the class.

```
$firstRoute = Reflection::getFirstDeepMetadata($classReflection, Route::class);
```

#### `hasDeepMetadata()`

[](#hasdeepmetadata)

```
public static function hasDeepMetadata(
    ReflectionClass $reflector,
    string $name
): bool
```

Checks if the class or any of its members have the specified attribute.

```
if (Reflection::hasDeepMetadata($classReflection, Inject::class)) {
    // Class uses dependency injection somewhere
}
```

### Reflection Creation Methods

[](#reflection-creation-methods)

#### `reflect()`

[](#reflect)

```
public static function reflect(mixed $var): null|ReflectionFunctionAbstract|ReflectionClass|ReflectionObject
```

Universal reflection method that automatically determines the appropriate reflection type.

```
$reflection = Reflection::reflect('MyClass');        // ReflectionClass
$reflection = Reflection::reflect($instance);        // ReflectionObject
$reflection = Reflection::reflect('strlen');         // ReflectionFunction
$reflection = Reflection::reflect([$obj, 'method']); // ReflectionMethod
```

#### `callable()`

[](#callable)

```
public static function callable(callable $callable): ReflectionFunctionAbstract
```

Creates reflection for callable types (functions, methods, closures).

```
$reflection = Reflection::callable('strlen');           // ReflectionFunction
$reflection = Reflection::callable([$obj, 'method']);   // ReflectionMethod
$reflection = Reflection::callable(fn() => true);      // ReflectionFunction
$reflection = Reflection::callable('Class::method');    // ReflectionMethod
```

#### `object()`

[](#object)

```
public static function object(object $object): ReflectionObject
```

Creates cached ReflectionObject for the given object instance.

```
$reflection = Reflection::object($userInstance);
echo $reflection->getName(); // 'User'
```

#### `class()`

[](#class)

```
public static function class(string $class): ?ReflectionClass
```

Creates cached ReflectionClass for the given class name. Returns null if class doesn't exist.

```
$reflection = Reflection::class('User');
$reflection = Reflection::class('NonExistentClass'); // null
```

Real-World Examples
-------------------

[](#real-world-examples)

### Dependency Injection Container

[](#dependency-injection-container)

```
use Bermuda\Reflection\Reflection;

class Container
{
    public function autowire(string $className): object
    {
        $reflection = Reflection::class($className);

        if (!$reflection) {
            throw new Exception("Class $className not found");
        }

        $constructor = $reflection->getConstructor();
        if (!$constructor) {
            return new $className();
        }

        $dependencies = [];
        foreach ($constructor->getParameters() as $parameter) {
            $type = $parameter->getType();
            if ($type && !$type->isBuiltin()) {
                $dependencies[] = $this->autowire($type->getName());
            }
        }

        return new $className(...$dependencies);
    }
}
```

### Route Discovery

[](#route-discovery)

```
use Bermuda\Reflection\Reflection;

class RouteDiscovery
{
    public function discoverRoutes(array $controllerClasses): array
    {
        $routes = [];

        foreach ($controllerClasses as $className) {
            $reflection = Reflection::class($className);

            // Find all Route attributes in the class
            $routeAttributes = Reflection::getDeepMetadata($reflection, Route::class);

            foreach ($routeAttributes as $path => $attributes) {
                foreach ($attributes as $route) {
                    $routes[] = [
                        'path' => $route->path,
                        'handler' => $path,
                        'methods' => $route->methods ?? ['GET']
                    ];
                }
            }
        }

        return $routes;
    }
}
```

### Validation with Attributes

[](#validation-with-attributes)

```
use Bermuda\Reflection\Reflection;

class Validator
{
    public function validate(object $entity): array
    {
        $reflection = Reflection::object($entity);
        $errors = [];

        foreach ($reflection->getProperties() as $property) {
            $value = $property->getValue($entity);

            // Check for validation attributes
            $required = Reflection::getFirstMetadata($property, Required::class);
            if ($required && empty($value)) {
                $errors[] = "{$property->getName()} is required";
            }

            $length = Reflection::getFirstMetadata($property, Length::class);
            if ($length && strlen($value) > $length->max) {
                $errors[] = "{$property->getName()} is too long";
            }
        }

        return $errors;
    }
}
```

### Event Handler Discovery

[](#event-handler-discovery)

```
use Bermuda\Reflection\Reflection;

class EventManager
{
    public function registerHandlers(object $listener): void
    {
        $reflection = Reflection::object($listener);

        foreach ($reflection->getMethods() as $method) {
            $eventHandler = Reflection::getFirstMetadata($method, EventHandler::class);

            if ($eventHandler) {
                $this->addEventListener(
                    $eventHandler->eventType,
                    [$listener, $method->getName()]
                );
            }
        }
    }
}
```

Performance Tips
----------------

[](#performance-tips)

1. **Leverage Caching**: The class automatically caches reflection objects, so prefer using static methods over creating new reflections manually
2. **Use Specific Searches**: When searching for specific attribute types, pass the class name to avoid unnecessary processing
3. **Deep Search Wisely**: Use deep search only when you need to search in class members, as it's more expensive than regular metadata retrieval
4. **Batch Operations**: When working with multiple classes, the caching system provides significant performance benefits

License
-------

[](#license)

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance52

Moderate activity, may be stable

Popularity8

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~34 days

Total

2

Last Release

340d ago

Major Versions

v1.0 → v2.02025-06-12

PHP version history (2 changes)v1.0PHP ^8.0 || ^8.1

v2.0PHP ^8.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/20490712?v=4)[Andrey Shelamkoff](/maintainers/Shelamkoff)[@Shelamkoff](https://github.com/Shelamkoff)

---

Top Contributors

[![Shelamkoff](https://avatars.githubusercontent.com/u/20490712?v=4)](https://github.com/Shelamkoff "Shelamkoff (33 commits)")

---

Tags

metadataphp-attributesphp84reflectionphpreflectionmetadatacachingattributes

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[voku/simple-cache

Simple Cache library

322.5M7](/packages/voku-simple-cache)[alekseykorzun/memcached-wrapper-php

Optimized PHP 5 wrapper for Memcached extension that supports dog-piling, igbinary and local storage

2984.6k1](/packages/alekseykorzun-memcached-wrapper-php)[rapidwebltd/rw-file-cache

RW File Cache is a PHP File-based Caching Library. Its syntax is designed to closely resemble the PHP memcache extension.

15191.3k7](/packages/rapidwebltd-rw-file-cache)

PHPackages © 2026

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