PHPackages                             dandoetech/resource-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. [API Development](/categories/api)
4. /
5. dandoetech/resource-registry

ActiveLibrary[API Development](/categories/api)

dandoetech/resource-registry
============================

Framework-agnostic Resource Registry for API resources (fields, relations, actions, policies).

v0.2.0(2d ago)107MITPHPPHP ^8.2CI passing

Since Mar 15Pushed 2d agoCompare

[ Source](https://github.com/dandoetech/resource-registry)[ Packagist](https://packagist.org/packages/dandoetech/resource-registry)[ Docs](https://github.com/dandoetech/resource-registry)[ RSS](/packages/dandoetech-resource-registry/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (3)Versions (3)Used By (7)

DanDoeTech Resource Registry
============================

[](#dandoetech-resource-registry)

> **Pre-release** — Architecture by senior tech lead, implementation largely AI-assisted with human review. Not fully reviewed. Architecture may change before v1.0.0.

Framework-agnostic resource definition layer for PHP. Define your API resources once — fields, relations, actions, computed fields — and let consumer packages (OpenAPI, BFF, generic API) derive everything else.

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

[](#installation)

```
composer require dandoetech/resource-registry
```

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

[](#quick-start)

Define a resource by extending the `Resource` base class:

```
use DanDoeTech\ResourceRegistry\Resource;
use DanDoeTech\ResourceRegistry\Builder\ResourceBuilder;
use DanDoeTech\ResourceRegistry\Definition\FieldType;

class ProductResource extends Resource
{
    protected function define(ResourceBuilder $b): void
    {
        $b->key('product')
          ->label('Product')
          ->timestamps()
          ->field('name', FieldType::String, nullable: false, rules: ['required', 'max:120'])
          ->field('price', FieldType::Float, nullable: false, rules: ['min:0'])
          ->field('category_id', FieldType::Integer, nullable: false)
          ->belongsTo('category', foreignKey: 'category_id')
          ->hasMany('reviews')
          ->computed('category_name', FieldType::String, via: 'category.name')
          ->computed('orders_count', FieldType::Integer, via: 'count:orders')
          ->filterable(['name', 'price', 'category_name'])
          ->sortable(['name', 'price', 'created_at', 'orders_count'])
          ->searchable(['name'])
          ->action('create')
          ->action('update')
          ->action('delete');
    }
}
```

Use the registry to access resource definitions:

```
use DanDoeTech\ResourceRegistry\Registry\ArrayRegistryDriver;
use DanDoeTech\ResourceRegistry\Registry\Registry;

// For standalone/testing use, ArrayRegistryDriver accepts array configs
$driver = new ArrayRegistryDriver([
    'product' => [
        'label' => 'Product',
        'fields' => [
            new FieldDefinition('name', FieldType::String, nullable: false),
            new FieldDefinition('price', FieldType::Float, nullable: false),
        ],
        'actions' => [new ActionDefinition('create')],
    ],
]);
$registry = new Registry($driver);

$product = $registry->getResource('product');
echo $product->getLabel(); // "Product"

foreach ($product->getFields() as $field) {
    echo $field->getName() . ': ' . $field->getType()->value;
}
```

> **Laravel users:** Use [`dandoetech/laravel-resource-registry`](https://github.com/dandoetech/laravel-resource-registry) for automatic class-based discovery, service provider binding, and Eloquent integration.

API Overview
------------

[](#api-overview)

### Contracts

[](#contracts)

All consumer packages type against these interfaces, never concrete classes.

InterfacePurpose`ResourceDefinitionInterface`Fields, relations, actions, computed fields, filtering/sorting config`FieldDefinitionInterface`Name, type, nullable, rules, unique, indexed, default, meta`RelationDefinitionInterface`Name, type, target resource, foreign/related keys, pivot table`ActionDefinitionInterface`Name, description, meta`ComputedFieldDefinitionInterface`Name, type, `via` (generic) or `resolver` (custom class)`RegistryDriverInterface``all()` and `find(string $key)` — pluggable backends### Enums

[](#enums)

EnumValues`FieldType``String`, `Integer`, `Float`, `Boolean`, `DateTime`, `Json`, `Date`, `Text`, `Email`, `Url`, `Enum``RelationType``BelongsTo`, `HasOne`, `HasMany`, `BelongsToMany`, `HasManyThrough`, `HasOneThrough`, `MorphTo`, `MorphMany`### Core Classes

[](#core-classes)

ClassRole`Resource`Abstract base class — extend and implement `define(ResourceBuilder)``ResourceBuilder`Fluent API for defining resources inside `define()``Registry`Main access point: `all()` and `getResource(string $key)``ArrayRegistryDriver`Array-config driver for standalone use and testing### Value Objects

[](#value-objects)

`ResourceDefinition`, `FieldDefinition`, `RelationDefinition`, `ActionDefinition`, `ComputedFieldDefinition` — `final class` implementations of their interfaces. Used internally by drivers and tests.

Computed Fields
---------------

[](#computed-fields)

Flat, derived columns for list views. Two strategies:

```
// Generic — system builds the query via relation metadata
->computed('category_name', FieldType::String, via: 'category.name')
->computed('orders_count', FieldType::Integer, via: 'count:orders')

// Custom — your resolver class handles the query
->computed('revenue', FieldType::Float, resolver: ProductRevenue::class)
```

Computed fields can be listed in `filterable()` and `sortable()` like regular fields.

Extending
---------

[](#extending)

Implement `RegistryDriverInterface` for custom backends:

```
use DanDoeTech\ResourceRegistry\Contracts\RegistryDriverInterface;

final class DatabaseRegistryDriver implements RegistryDriverInterface
{
    /** @return list */
    public function all(): array { /* ... */ }

    public function find(string $key): ?ResourceDefinitionInterface { /* ... */ }
}
```

Every interface has a `getMeta(): array` escape hatch for custom extensions.

Testing
-------

[](#testing)

```
composer install
composer test        # PHPUnit
composer qa          # cs:check + phpstan + test
```

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 86% of packages

Maintenance99

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

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

Total

2

Last Release

2d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7db403e7ef98a1eb428f771172dfa0edbd6f7c72d217fad0571992bee2cc089d?d=identicon)[dandoetech](/maintainers/dandoetech)

---

Top Contributors

[![dandoetech](https://avatars.githubusercontent.com/u/5097406?v=4)](https://github.com/dandoetech "dandoetech (31 commits)")

---

Tags

phpapimetadataresourcecrudregistry

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/dandoetech-resource-registry/health.svg)

```
[![Health](https://phpackages.com/badges/dandoetech-resource-registry/health.svg)](https://phpackages.com/packages/dandoetech-resource-registry)
```

###  Alternatives

[jstolpe/instagram-graph-api-php-sdk

Instagram Graph API PHP SDK

13994.9k1](/packages/jstolpe-instagram-graph-api-php-sdk)

PHPackages © 2026

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