Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Registry Laravel Package

gcego/registry

gcego/registry is a lightweight Laravel package that provides a simple registry for registering, resolving, and managing shared values, services, and configuration through a clean, fluent API, helping centralize reusable objects and app bindings.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a definition-discovery layer: you point it at directories ("roots"), each root is tagged with a "kind" and bound to a contract, and the package finds PHP definition files and resolves them into classes you can consume at runtime.

Minimal setup:

  1. Install and publish config:
    composer require <vendor>/<package>
    php artisan vendor:publish --tag=<package>-config
    
  2. In config/<package>.php, declare at least one root — the directory plus the kind and the contract its definitions must satisfy:
    'roots' => [
        'actions' => [
            'path'    => app_path('Actions'),
            'kind'    => 'action',
            'contract'=> App\Contracts\Action::class,
        ],
    ],
    
  3. Create a definition file inside that root. The file returns a DefinitionProvider:
    <?php
    use App\Actions\SendInvoice;
    
    return SendInvoice::class; // v1.1.0: may be omitted if the file declares exactly one DefinitionProvider
    
  4. Prime the registry:
    app(\Vendor\Package\Registry::class)->refresh();
    
    (or run the package's cache-rebuild artisan command in a deploy step).

Where to look first:

  • config/<package>.php — roots, kinds, contracts, cache path, verification flags.
  • Registry — refresh(), plus the accessor your app uses to resolve definitions.
  • DiscoveredFile — the value object you get back (path, resolved class, alternatives, roots). This is the primary debugging surface.

First real use case: auto-registering a set of handler/action classes (queueable actions, policies, webhook handlers, importers) so you never hand-edit a Provider array again. Put a folder in a root, drop in a class, refresh — it is available.

Implementation Patterns

One root per kind. The "kind" is the unit of intent, not just a directory. Keep folders and kinds 1:1 (Actions/, Policies/, Importers/). This makes contract-based resolution predictable and lets you later split or merge folders without touching consumer code.

Lean on class entrypoints (v1.1.0). For the common case — one class per file that implements DefinitionProvider — you can now drop the return Foo::class; line. Definition files become plain class files, which means your IDE refactors and static analysis treat them normally. Keep the explicit return when a file is intentionally a map of several definitions or declares helper classes alongside the provider.

Overlapping roots and contract routing. When two roots of different kinds match the same file (for example, a Domain/ folder scanned both as actions and as policies), v1.1.0 resolves it to the registered kind whose contract accepts the loaded definition. Use this deliberately: put shared domain folders in multiple roots and let the contract decide. Verify with:

$file = $registry->find(SendInvoice::class);
dump($file->roots());        // which roots matched
dump($file->alternatives);   // other candidate classes considered

Custom discovery with withAlternative(). When a file exposes more than one plausible class, or you are layering a new class over an old one for BC, attach candidates explicitly rather than relying on inference:

$file = $file->withAlternative(LegacyHandler::class);

The resolver still chooses by contract, so alternatives are a safe way to stage a migration.

Cache discipline in deploys. The registry is expensive to build and cheap to read once cached. Treat cache rebuild as a build artifact:

  • CI: run the cache-rebuild command after composer install --no-dev and code deploy.
  • Runtime: resolve from cache; do not call refresh() on every request.
  • Health check: run the cache-verification step in your smoke test so a corrupt/stale manifest fails the deploy, not production.

Testing pattern. Reset the registry per test so class-declaring files aren't carried across tests:

protected function setUp(): void
{
    parent::setUp();
    app(Registry::class)->refresh();
}

Then assert behaviour, not discovery internals. Use roots() only when asserting routing.

Long-running consumers. Queue workers, Octane and php artisan serve keep classes in memory. Resolve through the registry rather than storing concrete class strings in config, so a restart-and-refresh is the only operational action required after a deploy.

Gotchas and Tips

Restart workers after deploying class changes. A class-declaring entrypoint that changed after it was loaded now throws DefinitionLoadException asking for a restart. This is intentional and much better than silently serving the old class — but it means your deploy runbook must restart Horizon/queue workers and reload Octane. Add it to the deploy checklist.

Duplicate class declarations are now an exception, not a fatal. As of v1.1.0, if two entrypoints declare the same class you get a DefinitionLoadException. Inspect the message for both paths, then consolidate (one definition file owning the class) or register one path as an alternative on the other. Silent duplicates across roots are almost always a copy-paste error.

Registry::refresh() is safe now, but not free. Definition files that declare classes are included at most once per PHP process, so refresh, cache rebuilds, verification and cache reads no longer fatal with "cannot declare class". Refresh in dev and tests; avoid it on the hot path — it re-scans roots.

Ambiguous roots with no accepting contract. Contract-based routing only picks a kind if a contract accepts the loaded definition. If a file matches multiple kinds and none of the contracts match, you get a load exception. Symptom: a definition exists and is valid but is "invisible". Check roots() and confirm the class actually implements the contract for the kind you expect.

Files that declare no classes are unchanged. This is the compatibility guarantee for v1.1.0 — config-array-style definition files, closures, and plain return arrays behave exactly as before. Upgrade is non-breaking for that style; the class-entrypoint behaviour is purely additive.

Debugging checklist when a definition vanishes:

  1. Registry::refresh() and confirm the file is scanned (DiscoveredFile exists for the path).
  2. Check roots() — did the root you expect match?
  3. Check alternatives — was a different class inferred?
  4. Confirm the class implements the kind's contract.
  5. In a long-running process, restart and retry — a stale loaded class triggers DefinitionLoadException, not silent wrongness.

Extension points. DiscoveredFile is a value object (withAlternative() is immutable-style, returning a new instance), so custom discovery or test fixtures can compose candidates without mutating shared state. roots() is the stable hook for diagnostics and for routing decisions in your own code.

Config quirks. Cache path and verification are environment-sensitive — point them at a writable path per environment and keep the cache out of VCS. If you add roots at runtime (in a service provider), rebuild the cache after doing so or the manifest won't know about them.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo