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

Robot Loader Laravel Package

nette/robot-loader

RobotLoader automatically loads PHP classes, interfaces, and traits from specified directories by scanning files and caching the results. It spares you from manually requiring or registering each class, making it handy for legacy code or small projects without Composer.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. RobotLoader is a class-discovery engine plus an autoload hook, not a framework component. In a Laravel application the architecture already assumes Composer PSR-4 as the single source of class resolution; composer dump-autoload -o, classmaps, and vendor/composer/* are load-bearing in every deploy. The correct fit is therefore a scoped discovery primitive: point it at directories whose contents are genuinely unknown at build time (plugins, tenant modules, generated code, drop-in extensions) and leave first-party code to Composer. The place it plugs into is narrow and well-defined — service-provider registration, console command discovery, event-subscriber discovery, and manifest generation for admin UIs. Laravel already hand-rolls a version of this per subsystem (command load() loops, event discovery); this package generalizes it with a persistent cache and correct atomic writes. Framing it as an autoloader swap is an architectural regression and should be rejected at the PM level.

Integration feasibility. The public API is small enough to integrate in a day: addDirectory(), setCacheDirectory() (formerly setTempDirectory()), register(), refresh(), getClasses(), reportParseErrors(). No Laravel coupling, no service provider shipped, no config publishing — everything is ours to wire through one bounded singleton. That is a plus for control and a minus for onboarding ergonomics (see ramp-up). The main feasibility constraint is that a writable, absolute cache directory is mandatory, which is fine on traditional hosts and a gate on read-only container platforms.

Technical risk. Ranked:

  1. License is unresolved. Metadata reports NOASSERTION. The Nette ecosystem is typically BSD-3-Clause, but distribution in a commercial or SaaS product needs legal sign-off before adoption, not after. This is a checklist item with a hard stop, not a background task.
  2. Duplicate-load hazard. Two discovery mechanisms coexisting is the failure mode to design against: a class both Composer-mapped and RobotLoader-scanned, or a stale index shadowing a relocated file. Mitigation is strict directory scoping and an explicit "Composer owns this tree" policy, enforced in review.
  3. Case-sensitive lookups since v3.0.0. Developers on macOS/Windows will ship code that resolves locally and 500s in production. This is a predictable, recurring class of bug.
  4. PHP 8.1 floor. v4.x requires 8.1+. If any deployed surface is on 8.0, adoption means either a version pin to 3.4.x or an upgrade commitment that must be surfaced on the roadmap, not discovered in a sprint.
  5. Low ecosystem proof. Roughly 889 stars and zero listed dependents. It is respected (PHPStan, Nette) but narrowly consumed, which means we should expect to own integration problems ourselves rather than find them answered upstream.
  6. Boot-time coupling. If the temp directory is unwritable or a scanned file has a parse error and reportParseErrors is left on, the failure can take down boot rather than degrade one feature. That is a blast-radius decision worth making explicitly.

Key questions for engineering before I approve the spike. What is the actual inventory of dynamic surface area, with file counts and directory depth? Who owns the cache directory, and is it writable in every target environment including read-only/ephemeral ones? Can we pre-warm in the deploy pipeline so no user request ever triggers a rebuild? What happens on cache miss — do we fail open or fail closed, and what does the product look like in each case? Which classes are currently discovered by Laravel's built-in command/event discovery that we would be replacing, and do we replace or coexist? What is our exit plan if the package is abandoned — is the API surface small enough to vendor a fork?

Integration Approach

Stack fit. Bind exactly one configured loader as a singleton in a dedicated service provider, with directories, ignore patterns, accepted file patterns, and cache path all resolved from config. Nothing else in the application should construct a RobotLoader instance. Keep Composer authoritative and confine RobotLoader to an explicitly enumerated dynamic surface (e.g. app/Plugins/**), never app/ wholesale.

Migration path, in four gated phases.

  • Phase 0 — legal and spike. Confirm license terms; build a throwaway branch that scans the candidate directory and dumps getClasses(). Deliverable is a file count, a scan duration on a cold cache, and a warm-cache read cost. If the directory is small or scanned once per deploy, stop here — a recursive iterator is the cheaper answer.
  • Phase 1 — read-only discovery. Use the loader only to generate manifests (plugin lists, registered command names, available integrations). No autoload registration. This delivers user-visible value — an admin page, a capability registry — with near-zero blast radius and validates the cache behaviour under real deploys.
  • Phase 2 — scoped autoload registration. Call register() for the dynamic directories only, after Composer has had its chance. Add a regression test asserting a stable sorted getClasses() output so a cache or scoping regression fails CI rather than production.
  • Phase 3 — plugin/extension model. Only once Phases 1–2 have run a full release cycle without incident. This is where the product upside lives, and it is the only phase that justifies the dependency.

Compatibility. Pin ^4.1 and track the 4.x line deliberately; v4.1.3's setCacheDirectory() rename is a soft deprecation with no urgency, so there is no reason to be an early adopter of each patch. Use a per-environment cache key so dev and production indexes never mix, and ensure the cache path is absolute (storage/framework/cache/robotloader is a reasonable default, but verify it survives container rebuilds).

Sequencing constraints. Legal before code. Deploy-pipeline refresh() before any request-path rebuild. Manifest generation before autoloader registration. Autoloader registration before the plugin API. Do not let the plugin API ship in the same release as the first register() call — debugging a new autoloader and a new extension model simultaneously is how incidents get long.

Operational Impact

Maintenance. Source churn is low and disciplined: consistent PHP 8.x support tracking, PHPStan clean, phpDoc coverage, clear per-release notes with explicit BC breaks. That is a genuinely cheap dependency to carry. What we carry instead is integration maintenance — the service provider, config surface, deploy hook, and tests are ours forever, and with zero listed dependents there is no community of practice to lean on. Budget a named owner and a small quarterly check that the pinned line still supports our PHP range.

Support. User-facing support load comes almost entirely from three sources: plugin authors hitting parse errors, case-mismatch resolution failures that reproduce on Linux only, and "my plugin doesn't appear" (a cache staleness symptom). All three are diagnosable if we surface the loader's cache generation time and discovered-class count in a health or debug command. Without that, every one of these becomes an hour of engineering triage.

Scaling. Warm-cache lookups are cheap and scale with request volume without concern. Cold rebuilds scale with the size of the scanned tree and are the real cost — O(files) with a tokenizer pass. That is acceptable as a deploy step and unacceptable on a request path, so pre-warming is a structural requirement, not an optimization. On multi-node deployments behind shared storage, confirm that atomic cache writes and the lock behaviour hold on the actual filesystem in use; NFS semantics are worth testing rather than assuming.

Failure modes to instrument.

  • Cache directory missing or unwritable → boot-time hard failure; alert and fail the deploy, not the request.
  • Parse error in a scanned file → throws by default; keep reportParseErrors(false) in production and route parse failures into diagnostics so one bad plugin cannot take down the application.
  • Stale index after a file move or rename → silent "class not found" or, worse, resolution of an old path; the CI stability test and a deploy-time refresh() are the controls.
  • Windows/antivirus contention on cache rename → mitigated upstream since v3.2.x with retries, relevant only if Windows is a supported developer environment.
  • Duplicate class definition across Composer and RobotLoader scopes → fatal; prevent by directory policy and a lint check, not by runtime hope.

Ramp-up. A mid-level engineer can be productive on the library itself within a couple of days — the API is a handful of methods and the docs directory carries design rationale. The slower ramp is on the surrounding conventions: which directories are dynamic by policy, why two autoloaders exist, and what to do when discovery misbehaves. Those conventions need to be written down alongside the service provider, or every new hire will re-derive them by breaking production once.

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.
muka/shape-reader
tdt/json
refinery29/php-cs-fixer-config
hotmeteor/eco-env
mvaliolahi/hydrate
wearede/tbcpay-php
parsnick/steak
thibaud-dauce/mattermost-php
multilinguals/apollo-client
antaresbr/collection
kr0lik/phpstan-rules
loco/loco
starfederation/datastar-php
yupmin/modern-phystrix
stephenjude/extended-artisan-commands
lumphp/laravel-macroable
lumphp/laravel-collections
lumphp/laravel-contracts
sermepa/sermepa
arkecosystem/fortify