PHPackages                             josbeir/cakephp-attribute-registry - 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. josbeir/cakephp-attribute-registry

AbandonedArchivedCakephp-plugin[Utility &amp; Helpers](/categories/utility)

josbeir/cakephp-attribute-registry
==================================

CakePHP Attribute Registry Plugin - A plugin to manage and utilize PHP 8 attributes within CakePHP applications.

0.5.0(4mo ago)2621MITPHPPHP &gt;=8.2

Since Dec 22Pushed 2mo agoCompare

[ Source](https://github.com/josbeir/cakephp-attribute-registry)[ Packagist](https://packagist.org/packages/josbeir/cakephp-attribute-registry)[ RSS](/packages/josbeir-cakephp-attribute-registry/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (8)Versions (14)Used By (0)

[![PHPStan Level 8](https://camo.githubusercontent.com/ff3c7f8c8667ce643f47e74532748f673482a5f95d7d4269f925f2eebbe5117e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230382d627269676874677265656e)](https://github.com/josbeir/cakephp-attribute-registry)[![Build Status](https://github.com/josbeir/cakephp-attribute-registry/actions/workflows/ci.yml/badge.svg)](https://github.com/josbeir/cakephp-attribute-registry/actions)[![codecov](https://camo.githubusercontent.com/740d6bf5853d2286b2e74f24dd818ee27b237d1260af1a9119f84f0b693d0760/68747470733a2f2f636f6465636f762e696f2f6769746875622f6a6f73626569722f63616b657068702d6174747269627574652d72656769737472792f67726170682f62616467652e7376673f746f6b656e3d345647574a5154574835)](https://codecov.io/github/josbeir/cakephp-attribute-registry)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](https://opensource.org/licenses/MIT)[![PHP Version](https://camo.githubusercontent.com/744f8821cc27dec8b0013ade48179731a44eadf4f943e0b1d9ffcb93f80177de/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d382e322532422d626c75652e737667)](https://www.php.net/releases/8.2/en.php)[![CakePHP Version](https://camo.githubusercontent.com/e4555ed03e5c2dfca6a44248a236ee5d773386c599fe5a8df5c77a102163a9cb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f43616b655048502d352e322532422d7265642e737667)](https://cakephp.org/)[![Packagist Downloads](https://camo.githubusercontent.com/1e4b26406bb97f6df7a0b60b21ba50ec13376c011490ff4f394e7fd7f3d65718/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6a6f73626569722f63616b657068702d6174747269627574652d7265676973747279)](https://packagist.org/packages/josbeir/cakephp-attribute-registry)

CakePHP Attribute Registry Plugin
=================================

[](#cakephp-attribute-registry-plugin)

Warning

This plugin will become a CakePHP Core component in 6.x

A powerful CakePHP plugin for discovering, caching, and querying PHP 8 attributes across your application and plugins.

Table of Contents
-----------------

[](#table-of-contents)

- [Overview](#overview)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
    - [Configuration Options](#configuration-options)
    - [Disabling Cache](#disabling-cache)
    - [Smart Cache Validation](#smart-cache-validation)
    - [Cache Configuration](#cache-configuration)
    - [Attribute Argument Requirements](#attribute-argument-requirements)
- [Usage](#usage)
    - [Accessing the AttributeRegistry](#accessing-the-attributeregistry)
        - [Option 1: Singleton](#option-1-singleton)
        - [Option 2: Dependency Injection](#option-2-dependency-injection)
    - [Discovery Methods](#discovery-methods)
        - [Discover All Attributes](#discover-all-attributes)
        - [Fluent Filtering with AttributeCollection](#fluent-filtering-with-attributecollection)
        - [Find by Attribute Name](#find-by-attribute-name)
        - [Find by Class Name](#find-by-class-name)
        - [Find by Target Type](#find-by-target-type)
        - [Cache Management](#cache-management)
    - [Events](#events)
    - [Working with AttributeInfo](#working-with-attributeinfo)
    - [Example: Building a Route Registry](#example-building-a-route-registry)
- [Console Commands](#console-commands)
    - [Discover Attributes](#discover-attributes)
    - [List Attributes](#list-attributes)
    - [Inspect Attributes](#inspect-attributes)
- [DebugKit Panel](#debugkit-panel)
- [Testing](#testing)
- [Contributing](#contributing)
- [License](#license)
- [Credits](#credits)

Overview
--------

[](#overview)

The CakePHP Attribute Registry Plugin provides a centralized system for discovering and managing PHP 8 attributes throughout your CakePHP application. It scans your codebase for attributes on classes, methods, properties, parameters, and constants, then caches the results for fast retrieval.

**Key Features:**

- 🔍 **Automatic Discovery** - Scans PHP files for attributes using configurable glob patterns
- 💾 **Built-in Caching** - Caches discovered attributes
- 🔎 **Flexible Querying** - Find attributes by name, class, or target type
- 🔌 **Plugin Support** - Automatically scans all loaded CakePHP plugins
- 🖥️ **CLI Tools** - Console commands for discovery, listing, and inspection
- 🏗️ **Service-Oriented** - Clean architecture with dependency injection via CakePHP's container
- 🎯 **Event System** - Hook into discovery and caching lifecycle for logging, monitoring, and custom integrations
- 🐛 **DebugKit Panel** - Visual panel for browsing discovered attributes during development

**Supported Attribute Targets:**

PHP TargetConstantSupportedExampleClass`Attribute::TARGET_CLASS`✅`#[Route] class MyController`Method`Attribute::TARGET_METHOD`✅`#[Get] public function index()`Property`Attribute::TARGET_PROPERTY`✅`#[Column] public int $id`Parameter`Attribute::TARGET_PARAMETER`✅`function show(#[FromPath] int $id)`Class Constant`Attribute::TARGET_CLASS_CONSTANT`✅`#[Deprecated] const STATUS = 1`Function`Attribute::TARGET_FUNCTION`❌Standalone functions not supportedNote

Standalone functions (`TARGET_FUNCTION`) are not supported because the plugin uses class-based reflection. In typical CakePHP applications, attributes are primarily used on classes and their members.

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

[](#requirements)

- PHP 8.2 or higher
- CakePHP 5.2 or higher

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

[](#installation)

Install the plugin using Composer:

```
composer require josbeir/cakephp-attribute-registry
```

Load the plugin in your `src/Application.php`:

```
bin/cake plugin load AttributeRegistry
```

Configuration
-------------

[](#configuration)

The plugin works out of the box with sensible defaults.

### Configuration Options

[](#configuration-options)

```
// config/app_attribute_registry.php
return [
    'AttributeRegistry' => [
        'cache' => [
            // Enable/disable caching (default: true)
            // When disabled, attributes are re-discovered on every request
            'enabled' => true,
            // Cache directory (defaults to CACHE . 'attribute_registry' . DS)
            'path' => CACHE . 'attribute_registry' . DS,
            // Validate file modification times on cache retrieval (default: false)
            // When enabled, cached entries are validated against file timestamp changes
            // Useful in development to auto-rebuild cache when files change
            // Example: Configure::read('debug') enables validation only in debug mode
            'validateFiles' => false,
        ],
        'scanner' => [
            // Glob patterns for files to scan (relative to base paths)
            'paths' => [
                'src/**/*.php',
            ],
            // Glob patterns for paths to exclude
            'exclude_paths' => [
                'vendor/**',
                'tmp/**',
                'logs/**',
                'tests/**',
                'webroot/**',
            ],
            // Attribute classes to exclude from discovery
            'exclude_attributes' => [
                'Override',           // Exact FQCN match
                'App\\Internal\\*',   // Namespace wildcard
            ],
        ],
    ],
];
```

### Disabling Cache

[](#disabling-cache)

You can disable caching for development purposes by setting `cache.enabled` to `false`:

```
'AttributeRegistry' => [
    'cache' => [
        'enabled' => false,
    ],
],
```

Warning

Disabling cache will cause attributes to be re-discovered on every request, which may impact performance. Only use this for development.

### Smart Cache Validation

[](#smart-cache-validation)

Instead of disabling the cache entirely, you can enable **file modification time validation** to automatically invalidate stale cache entries when files change:

```
use Cake\Core\Configure;

'AttributeRegistry' => [
    'cache' => [
        'enabled' => true,
        // Auto-enable validation in debug mode
        'validateFiles' => Configure::read('debug', false),
    ],
],
```

When `validateFiles` is enabled:

- ✅ **Cache remains active** - Fast performance
- ✅ **Auto-detects changes** - Validates file modification times (filemtime) on cache load
- ✅ **Granular invalidation** - Only rebuilds when cached files are modified

Important

**Limitation:** This only validates **existing cached entries**. When you add **new attributes** to your codebase, you still need to manually refresh the cache:

```
bin/cake attributes cache
# or in code:
$registry->clearCache();
```

Tip

This is the recommended approach for development - you get cache performance benefits and automatic detection of changes to existing attributes, while only needing manual cache clearing when adding new ones.

### Cache Configuration

[](#cache-configuration)

The plugin uses **compiled cache files** for zero-cost attribute caching. Discovered attributes are stored as pre-compiled PHP files with direct object instantiation, leveraging OPcache for maximum performance.

**Cache Location**: By default, cache files are stored in `tmp/cache/attribute_registry/`. You can customize this path:

```
'AttributeRegistry' => [
    'cache' => [
        'path' => CACHE . 'attributes' . DS, // Custom cache directory
    ],
],
```

**How it Works**:

1. During discovery, attributes are scanned and serialized into executable PHP files
2. The compiled files contain direct `AttributeInfo` object instantiation code
3. OPcache automatically optimizes these files for near-zero overhead on subsequent loads

**Performance**: Compiled cache eliminates deserialization overhead entirely - loading cached attributes is as fast as requiring a PHP file with predefined objects.

**Automatic Cache Clearing**: When you run `bin/cake cache clear_all`, the AttributeRegistry cache is automatically refreshed via the attribute discovery process. Disable this behavior if needed:

```
'AttributeRegistry' => [
    'disableCacheClearListener' => true,
],
```

### Attribute Argument Requirements

[](#attribute-argument-requirements)

The compiled cache uses [brick/varexporter](https://github.com/brick/varexporter) to serialize attribute arguments. All common PHP types are fully supported:

**Supported Types:**

- Scalars: `string`, `int`, `float`, `bool`, `null`
- Arrays of any supported types
- Enums (PHP 8.1+)
- Objects (automatically handled via reflection)

**Object Arguments** work seamlessly without requiring any special methods:

```
class Translation
{
    public function __construct(
        public string $key,
        public string $domain = 'default',
        public ?string $locale = null,
    ) {}
}

class ValidationRule
{
    public function __construct(
        public string $rule,
        public array $options = [],
    ) {}
}

#[Attribute]
class Translatable
{
    public function __construct(
        public Translation $translation,
        public ValidationRule $validation,
    ) {}
}

// Usage on entity property
class Article
{
    #[Translatable(
        translation: new Translation('article.title', 'cms', 'en_US'),
        validation: new ValidationRule('maxLength', ['max' => 255])
    )]
    public string $title;
}
```

Objects are serialized using reflection-based strategies automatically.

Tip

If caching fails due to unsupported types (resources, closures), an error will be logged at `logs/error.log` and the attribute will be skipped from the cache.

Usage
-----

[](#usage)

### Accessing the AttributeRegistry

[](#accessing-the-attributeregistry)

The `AttributeRegistry` can be accessed in two ways:

#### Option 1: Singleton

[](#option-1-singleton)

Use `getInstance()` anywhere in your application without requiring dependency injection:

```
use AttributeRegistry\AttributeRegistry;

// Anywhere in your code
$registry = AttributeRegistry::getInstance();
$routes = $registry->findByAttribute('Route');
```

#### Option 2: Dependency Injection

[](#option-2-dependency-injection)

The registry is also available via CakePHP's dependency injection container:

```
use AttributeRegistry\AttributeRegistry;

// In a Controller
class MyController extends AppController
{
    public function index(AttributeRegistry $registry): Response
    {
        $routes = $registry->findByAttribute('Route');
        // ...
    }
}

// In a Command
class MyCommand extends Command
{
    public function __construct(
        private readonly AttributeRegistry $registry,
    ) {
        parent::__construct();
    }
}
```

Both approaches return the same singleton instance, ensuring consistent caching behavior.

### Discovery Methods

[](#discovery-methods)

The `AttributeRegistry` service provides several methods for finding attributes:

Note

All query methods (`findByAttribute`, `findByClass`, `findByTargetType`) internally call `discover()`. The discovery result is cached after the first call, so subsequent queries within the same request are fast. When adding new attributes to your codebase, clear the cache using `$registry->clearCache()` or run `bin/cake attributes cache` to refresh the registry.

#### Discover All Attributes

[](#discover-all-attributes)

The `discover()` method returns an `AttributeCollection` - a powerful extension of CakePHP's Collection with domain-specific filter methods:

```
// Get all discovered attributes as a collection
$attributes = $registry->discover();

// Convert to array when needed
$array = $attributes->toList();
```

#### Fluent Filtering with AttributeCollection

[](#fluent-filtering-with-attributecollection)

The `AttributeCollection` provides chainable filter methods for building complex queries. All filter methods accept multiple arguments with **OR logic** (matches any):

```
use AttributeRegistry\Enum\AttributeTargetType;

// Filter by exact attribute class (single or multiple)
$routes = $registry->discover()
    ->attribute(Route::class)
    ->toList();

// Multiple attributes - matches Route OR Get OR Post
$httpAttributes = $registry->discover()
    ->attribute(Route::class, Get::class, Post::class)
    ->toList();

// Filter by namespace pattern (supports wildcards)
$appAttributes = $registry->discover()
    ->namespace('App\\Controller\\*')
    ->toList();

// Multiple namespaces
$attributes = $registry->discover()
    ->namespace('App\\Controller\\*', 'App\\Model\\*')
    ->toList();

// Filter by target type (single or multiple)
$methodAttributes = $registry->discover()
    ->targetType(AttributeTargetType::METHOD)
    ->toList();

// Methods OR properties
$memberAttributes = $registry->discover()
    ->targetType(AttributeTargetType::METHOD, AttributeTargetType::PROPERTY)
    ->toList();

// Filter by exact class name (single or multiple)
$controllerAttributes = $registry->discover()
    ->className(UsersController::class, PostsController::class)
    ->toList();

// Partial matching with contains methods
$routeAttributes = $registry->discover()
    ->attributeContains('Route')
    ->toList();

$controllerAttributes = $registry->discover()
    ->classNameContains('Controller')
    ->toList();
```

**Combining Filters**

Chain multiple filters to narrow down results (uses AND logic between different filter types):

```
// Find all Route attributes on methods in the App\Controller namespace
$routes = $registry->discover()
    ->attribute(Route::class)
    ->namespace('App\\Controller\\*')
    ->targetType(AttributeTargetType::METHOD)
    ->toList();
```

**Using Standard Collection Methods**

Since `AttributeCollection` extends CakePHP's Collection, all standard methods are available:

```
// Group attributes by class
$grouped = $registry->discover()
    ->attribute(Route::class)
    ->groupBy(fn($attr) => $attr->className)
    ->toArray();

// Filter with custom logic
$postRoutes = $registry->discover()
    ->attribute(Route::class)
    ->filter(fn($attr) => ($attr->arguments['method'] ?? 'GET') === 'POST')
    ->toList();

// Map to extract specific data
$paths = $registry->discover()
    ->attribute(Route::class)
    ->map(fn($attr) => $attr->arguments['path'] ?? '/')
    ->toList();

// Count results
$count = $registry->discover()
    ->attribute(Route::class)
    ->count();

// Check if any exist
$hasRoutes = $registry->discover()
    ->attribute(Route::class)
    ->isEmpty() === false;
```

#### Find by Attribute Name

[](#find-by-attribute-name)

```
// Find all usages of a specific attribute
$routes = $registry->findByAttribute(Route::class);
$columns = $registry->findByAttribute(Column::class);

// Partial matching is also supported
$routes = $registry->findByAttribute('Route');
```

#### Find by Class Name

[](#find-by-class-name)

```
// Find attributes on a specific class
$attributes = $registry->findByClass(UserController::class);

// Partial matching is also supported
$attributes = $registry->findByClass('Controller');
```

#### Find by Target Type

[](#find-by-target-type)

```
use AttributeRegistry\Enum\AttributeTargetType;

// Find all class-level attributes
$classAttributes = $registry->findByTargetType(AttributeTargetType::CLASS_TYPE);

// Find all method-level attributes
$methodAttributes = $registry->findByTargetType(AttributeTargetType::METHOD);

// Find all property-level attributes
$propertyAttributes = $registry->findByTargetType(AttributeTargetType::PROPERTY);
```

#### Cache Management

[](#cache-management)

```
// Clear all cached attribute data (removes compiled cache files)
$registry->clearCache();

// Warm the cache (clear and rediscover - regenerates compiled files)
$registry->warmCache();

// Check if cache is enabled
if ($registry->isCacheEnabled()) {
    // Cache is active
}
```

The cache records file modification timestamps (`filemtime`) for discovered attributes, which you can use to detect when source files have changed and decide when to rebuild or clear the cache.

### Events

[](#events)

The AttributeRegistry dispatches custom event classes at key points in the discovery and caching lifecycle. These typed event classes provide better IDE support and type safety compared to generic events.

**Available Events:**

Event ClassEvent NameWhen FiredMethodsDescription`BeforeDiscoverEvent``AttributeRegistry.beforeDiscover`Start of `discover()``getSubject()`Fired before attribute discovery begins (every call)`AfterDiscoverEvent``AttributeRegistry.afterDiscover`End of `discover()``getSubject()`, `getAttributes()`Fired after discovery completes with the result collection`BeforeScanEvent``AttributeRegistry.beforeScan`Before file scanning`getSubject()`Fired only when scanning files (not when using cached data)`AfterScanEvent``AttributeRegistry.afterScan`After file scanning`getSubject()`, `getAttributes()`Fired after scanning completes with discovered attributes`BeforeCacheClearEvent``AttributeRegistry.beforeCacheClear`Start of `clearCache()``getSubject()`Fired before clearing the cache`AfterCacheClearEvent``AttributeRegistry.afterCacheClear`End of `clearCache()``getSubject()`, `wasCleared()`Fired after cache clearing with success statusEach event class extends `Cake\Event\Event` and provides:

- A `NAME` constant for type-safe event name references
- A typed `getSubject()` method returning the `AttributeRegistry` instance
- Additional typed accessor methods for event-specific data

**Event Listener Examples:**

```
use Cake\Event\EventInterface;
use Cake\Event\EventManager;
use AttributeRegistry\Event\AfterDiscoverEvent;
use AttributeRegistry\Event\AfterScanEvent;
use AttributeRegistry\Event\AfterCacheClearEvent;
use AttributeRegistry\Event\BeforeScanEvent;

// Listen using typed event classes for better IDE support
EventManager::instance()->on(
    AfterDiscoverEvent::NAME,
    function (AfterDiscoverEvent $event) {
        // Typed access to attributes collection
        $attributes = $event->getAttributes();
        $count = $attributes->count();

        Log::info("Discovered {$count} attributes");
    }
);

// Track scanning performance with typed events
$scanTimer = null;

EventManager::instance()->on(
    BeforeScanEvent::NAME,
    function (BeforeScanEvent $event) use (&$scanTimer) {
        $scanTimer = microtime(true);
    }
);

EventManager::instance()->on(
    AfterScanEvent::NAME,
    function (AfterScanEvent $event) use (&$scanTimer) {
        $duration = microtime(true) - $scanTimer;
        // Type-safe method access
        $attributes = $event->getAttributes();

        Log::info(sprintf(
            'Scanned %d attributes in %.2fms',
            $attributes->count(),
            $duration * 1000
        ));
    }
);

// Clear related caches when AttributeRegistry cache is cleared
EventManager::instance()->on(
    AfterCacheClearEvent::NAME,
    function (AfterCacheClearEvent $event) {
        // Type-safe boolean check
        if ($event->wasCleared()) {
            // Clear your custom route cache, API documentation cache, etc.
            Cache::delete('my_route_cache');
            Cache::delete('api_docs');
        }
    }
);

// You can also use generic EventInterface if you prefer
EventManager::instance()->on(
    'AttributeRegistry.afterDiscover',
    function (EventInterface $event) {
        // Generic access still works, but without IDE autocomplete
        $attributes = $event->getData('attributes');
        // ...
    }
);
```

### Working with AttributeInfo

[](#working-with-attributeinfo)

Each discovered attribute is returned as an `AttributeInfo` value object:

```
use AttributeRegistry\ValueObject\AttributeInfo;

foreach ($registry->discover() as $attr) {
    // Basic information
    echo $attr->attributeName;  // Full attribute class name
    echo $attr->className;      // Class containing the attribute
    echo $attr->filePath;       // File where attribute was found
    echo $attr->lineNumber;     // Line number in file

    // Attribute arguments
    print_r($attr->arguments);  // Array of constructor arguments

    // Target information
    echo $attr->target->type->value;    // 'class', 'method', 'property', etc.
    echo $attr->target->targetName;     // Name of the target element
    echo $attr->target->parentClass;    // Parent class (for methods/properties)

    // Instantiate the actual attribute
    $instance = $attr->getInstance();

    // With type safety
    $route = $attr->getInstance(MyRoute::class);
}
```

### Example: Building a Route Registry

[](#example-building-a-route-registry)

```
use Attribute;

#[Attribute(Attribute::TARGET_CLASS)]
class Route
{
    public function __construct(
        public string $path,
        public string $method = 'GET',
    ) {}
}

#[Attribute(Attribute::TARGET_METHOD)]
class Get
{
    public function __construct(
        public ?string $path = null,
    ) {}
}

// Controller
#[Route('/users')]
class UsersController
{
    #[Get('/')]
    public function index(): void {}

    #[Get('/{id}')]
    public function view(int $id): void {}
}

// In your application
$routes = $registry->findByAttribute(Route::class);
foreach ($routes as $routeInfo) {
    $route = $routeInfo->getInstance(Route::class);
    echo "Route: {$route->path} ({$route->method})";
}
```

Console Commands
----------------

[](#console-commands)

The plugin provides three console commands for managing attributes:

### Cache Attributes

[](#cache-attributes)

Manage the attribute cache (clear and rebuild):

```
bin/cake attributes cache
```

Output:

```
Clearing attribute cache...
Discovering attributes...
Discovered 42 attributes in 0.234s

```

Options:

- `--no-clear` - Skip clearing the cache before discovering
- `--clear-only` - Only clear cache without discovering attributes
- `--validate` - Validate cache integrity after building

Example with validation:

```
bin/cake attributes cache --validate
```

Output:

```
Clearing attribute cache...
Discovering attributes...
Discovered 42 attributes in 0.234s
Validating cache integrity...
Cache validation passed: 42 attributes, 15 files

```

### List Attributes

[](#list-attributes)

List discovered attributes with optional filtering:

```
# List all attributes
bin/cake attributes list

# Filter by attribute name
bin/cake attributes list --attribute Route

# Filter by class name
bin/cake attributes list --class UserController

# Filter by target type
bin/cake attributes list --type method
```

Output:

```
Found 5 attributes:

+---------------------------+----------------------------------+----------+--------+-----------------+
| Attribute                 | Class                            | Plugin   | Type   | Target          |
+---------------------------+----------------------------------+----------+--------+-----------------+
| App\Attribute\Route       | App\Controller\UsersController   | -        | class  | UsersController |
| App\Attribute\Get         | App\Controller\UsersController   | -        | method | index           |
| App\Attribute\Get         | App\Controller\UsersController   | -        | method | view            |
| MyPlugin\Attribute\Cache  | MyPlugin\Model\Table\PostsTable  | MyPlugin | method | findPublished   |
| MyPlugin\Attribute\Queue  | MyPlugin\Service\EmailService    | MyPlugin | method | sendWelcome     |
+---------------------------+----------------------------------+----------+--------+-----------------+

```

### Inspect Attributes

[](#inspect-attributes)

View detailed information about specific attributes:

```
# Inspect by attribute name
bin/cake attributes inspect Route

# Inspect attributes on a specific class
bin/cake attributes inspect --class UserController
bin/cake attributes inspect -c UserController
```

Output:

```
Found 2 attributes for attribute "Route":

1. App\Attribute\Route
   Class: App\Controller\UsersController
   Target: UsersController (class)
   File: /path/to/src/Controller/UsersController.php:12
   Arguments:
     - path: /users
     - method: GET

```

DebugKit Panel
--------------

[](#debugkit-panel)

When [DebugKit](https://github.com/cakephp/debug_kit) is installed, the plugin automatically registers a panel for browsing discovered attributes.

[![DebugKit Panel](docs/debug_kit_screenshot.png)](docs/debug_kit_screenshot.png)

The panel provides:

- Overview of all discovered attributes grouped by type or file
- Search functionality to filter attributes
- Re-discover button to refresh the attribute cache

Testing
-------

[](#testing)

Run the test suite:

```
# Run all tests
composer test

# Run with coverage
composer test-coverage

# Run PHPStan analysis
composer phpstan

# Check code style
composer cs-check

# Fix code style
composer cs-fix

# Run Rector checks
composer rector-check
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please follow these guidelines:

1. **Code Standards**: Follow CakePHP coding standards
2. **Tests**: Add tests for new features
3. **PHPStan**: Ensure level 8 compliance
4. **Documentation**: Update README for new features

### Development Setup

[](#development-setup)

```
# Clone the repository
git clone git@github.com:josbeir/cakephp-attribute-registry.git
cd cakephp-attribute-registry

# Install dependencies
composer install

# Run tests
composer test

# Run static analysis
composer phpstan
```

License
-------

[](#license)

This plugin is open-sourced software licensed under the [MIT license](LICENSE.md).

Credits
-------

[](#credits)

- Built with [CakePHP](https://cakephp.org/)

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance81

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity44

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 ~1 days

Total

10

Last Release

122d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2899d7bd057eecff34549480753213e1b19652f7f726db2d971b6b0fa69d4c14?d=identicon)[josbeir](/maintainers/josbeir)

---

Top Contributors

[![josbeir](https://avatars.githubusercontent.com/u/26058?v=4)](https://github.com/josbeir "josbeir (57 commits)")

---

Tags

plugincakephpattributesregistryphp8

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Type Coverage Yes

### Embed Badge

![Health badge](/badges/josbeir-cakephp-attribute-registry/health.svg)

```
[![Health](https://phpackages.com/badges/josbeir-cakephp-attribute-registry/health.svg)](https://phpackages.com/packages/josbeir-cakephp-attribute-registry)
```

###  Alternatives

[cakedc/tiny-mce

TinyMCE Plugin for CakePHP

10790.2k](/packages/cakedc-tiny-mce)[dereuromark/cakephp-dto

A CakePHP plugin for generating immutable Data Transfer Objects with full type safety

2988.9k3](/packages/dereuromark-cakephp-dto)[dereuromark/cakephp-geo

A CakePHP plugin around geocoding tools and helpers.

51174.9k4](/packages/dereuromark-cakephp-geo)[dereuromark/cakephp-calendar

A CakePHP plugin to easily create calendars.

1646.8k1](/packages/dereuromark-cakephp-calendar)[dereuromark/cakephp-flash

A CakePHP plugin around powerful flash message handling.

1228.6k2](/packages/dereuromark-cakephp-flash)[dereuromark/cakephp-data

A CakePHP plugin containing lots of useful and reusable data containers

1418.4k3](/packages/dereuromark-cakephp-data)

PHPackages © 2026

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