lorisleiva/lody
Lody is a Laravel package that loads PHP files and classes from any path as lazy collections, letting you filter by abstraction or interface and chain methods like each. It resolves classnames via PSR-4 conventions and paths relative to your app's base path.
What we are actually evaluating. Lody is a class-and-file discovery utility, not a framework extension. It exposes a static facade (Lody::files, Lody::classes) that composes Symfony Finder, Composer's vendor/composer/autoload_psr4.php mapping, and Laravel's LazyCollection to return two custom collection types with chainable filters: classExists, isAbstract/isNotAbstract, isInstanceOf/isNotInstanceOf, hasTrait/doesNotHaveTrait, and hasMethod/hasStaticMethod/hasNonStaticMethod. There is no config file to publish, no migration, no persistence, and no service-provider surface beyond three optional static resolver registrations. The evaluation is therefore narrow and product-shaped: do we have a recurring need for convention-based discovery, and can we absorb a small single-maintainer 0.x dependency to get it?
Architecture fit.
app/Plugins, app/Workflow/Nodes, app/Billing/Handlers) and qualify via an interface, an abstract base, or a PHP attribute. Discovery replaces hand-maintained registration arrays — the classic source of merge conflicts and forgotten registrations in multi-team Laravel repositories.Lody::setBasePath() makes it usable, but the value proposition leans on base_path() and Laravel collections. A non-Laravel PHP service should use Symfony Finder directly.Integration feasibility. Installation is one composer require and works on first call. The real effort is policy, not code: naming the discovery convention, defining and owning the qualifying contract, deciding whether discovery runs at boot or against a deploy-time manifest, and documenting the plugin contract for contributors. A competent Laravel engineer reaches a proof of concept inside a day. The costed work is the wrapper, the manifest cache, observability around count drift, and the authoring guide — roughly a one-to-two-week increment including tests, not a one-line adoption.
Technical risk.
0.x versioning, single maintainer. This is a well-crafted utility with a small audience, not a community standard. Adopt only with an exact pin and a written exit plan; the low overall score here against a much higher opportunity score is a signal to replicate the pattern defensively rather than depend on it uncritically.--classmap-authoritative autoloading, or namespaces that do not map cleanly to a directory resolve to names that fail classExists() and vanish without an error. v0.7.1 formalises this behaviour: a missing path returns an empty collection rather than throwing. For a plugin registry, "quietly registered fewer handlers than exist" is the failure mode that costs us production incidents.use, expensive static initializer) can break the boot path or slow it. Discovery is unsafe against untrusted or partially installed third-party code.Key questions for engineering before we commit.
composer dump-autoload before cache warm?0.x single-maintainer dependency, and what is the trigger to vendor or reimplement (~200 lines against Symfony Finder)?Stack fit. Native to Laravel 10–13 and PHP 8.1+; no PHP extension requirements, no published configuration, MIT licensed. It fits our existing stack without a Composer constraint fight, which is the main reason it is viable at all.
Migration path. Adoption is additive and reversible — nothing in the package touches existing wiring until we call it. Recommended path: (1) pick exactly one domain with an existing hand-maintained registry, (2) introduce Lody behind an internal DiscoveryService wrapper, (3) keep the old registry in place and assert both produce the same set, (4) flip the call site once parity holds, (5) replicate the wrapper across the next two domains without touching their registration code. This also gives us the seam to swap the implementation later without a repo-wide refactor.
Compatibility.
^0.7.--classmap-authoritative, validate discovery against a staging build before trusting it — this is where the heuristic breaks quietly.Lody types in its public signatures so a future fork or reimplementation is a single-file change.Sequencing.
DiscoveryService plus a deploy-time manifest cache (Artisan command writing discovered classnames to a cached file), with a boot-time fallback for local development.Maintenance. Low code surface, non-trivial dependency surface. No migrations, no runtime state, no background jobs. Our ongoing cost is the pin, the framework-upgrade coupling, and the wrapper we own. Budget roughly a half-day per Laravel major to validate the upgrade, plus a standing decision to fork or reimplement if the maintainer stops releasing.
Support. Community-only, single maintainer, no vendor SLA. Our wrapper is the support boundary: teams file against us, not GitHub. That means we own triage for the failure modes below, and we should carry a tested fallback (a small Symfony Finder implementation of the same interface) from day one rather than writing one during an incident.
Scaling. Discovery cost is O(files scanned) with autoload and reflection per candidate. It does not belong on the request path. The scaling answer is structural: build a manifest once at deploy, cache it, and at runtime read the manifest rather than the filesystem. That keeps boot cost flat as the codebase grows and makes discovery behaviour identical across web and queue workers. Without the manifest, expect boot-time regressions that surface as slow cold starts and unpredictable queue worker spin-up.
Failure modes to instrument.
Ramp-up. Engineers familiar with Laravel collections will read the chainable API in minutes; the README is sufficient and the filter set is self-describing. The genuine onboarding load is on plugin authors, who must know the directory convention, the qualifying contract, and that classes must be autoloadable and PSR-4-resolvable to be discovered at all. That guide is the deliverable most likely to be under-scoped. Allocate a day for authoring it and a review pass with the first consuming team; without it, the convention degrades into tribal knowledge and the discovery mechanism becomes less predictable than the registry it replaced.
How can I help you explore Laravel packages today?