laravel/surveyor
Laravel Surveyor is a mostly static analysis tool that parses PHP files to extract detailed metadata about classes, methods, properties, and return types, exposing it in a structured format other tools can consume. Currently in beta.
Architecture fit. Surveyor is an in-process library, not a service or CLI. You resolve Analyzer from the container, hand it a file path or FQCN, and get back ClassLikeResult objects carrying methods, properties, constants, validation rules, and a typed type graph. That makes it a good fit for products that introspect a Laravel app to generate something — TypeScript/API contract generation, documentation, admin or scaffold generation, IDE/agent tooling. It is a poor fit as a generic "analyze any PHP" component, and a poor fit for a polyglot pipeline without taking the asArray()/asJson() serialization path.
Integration feasibility. Install is one Composer require; first result is a few lines. The real constraint is that it must run inside a bootstrapped Laravel app — it reads container bindings and opens a database connection to inspect Eloquent models. That rules out dropping it into a bare CLI script or a stateless worker and makes it an artisan-command/CI-step shape rather than a runtime dependency.
Technical risk.
Ignored/ConditionallyIgnored attributes and comment tags are the only thing standing between a database column and a shipped bundle.Key questions.
laravel/ranger already provide the shaping layer we would otherwise build?Stack fit. Highest possible fit for a Laravel monolith introspecting itself: container-native, Eloquent-aware, env-configured cache (SURVEYOR_CACHE_ENABLED, SURVEYOR_CACHE_DIR). No fit for non-Laravel PHP frameworks. Do not attempt to run it from a separate analysis service on day one.
Migration path. Effectively greenfield — there is no incumbent to displace. The critical move is to wrap Surveyor behind our own narrow interface (e.g. SchemaExtractor returning our DTOs) and never let Laravel\Surveyor\Types\* or ClassLikeResult leak into domain code. With a beta dependency and zero dependents, the adapter is the entire risk mitigation: a v1.0 breaking change, an abandonment, or a fork becomes a one-file swap rather than a refactor.
Compatibility. Verify Composer constraints per target app before committing — beta packages often bump minimum PHP/Laravel in minor releases. Verify behavioral parity across local, CI, and any environment where models are analyzed; divergent DB or binding state is the most likely source of "works on my machine" metadata.
Sequencing.
registerConditionResolver, and write tests asserting sensitive fields are absent from output.Maintenance. We inherit beta upgrade risk. Budget a recurring task per release: read changelog, bump pinned version, run golden tests, fix adapter. Our own surface — the adapter, the marker registry (Markers::registerTags, registerAttributes, condition resolver) — is code we own and must test. Assume the possibility of vendoring a fork if the package stalls.
Support. No commercial support, no LTS, no deprecation guarantees pre-v1.0. Support is the GitHub issue tracker and the changelog. Low adoption means bugs we hit may sit unfixed; plan for self-service.
Scaling. Two axes. Codebase size: analysis is per-file with dependency-tracked caching, and memory is the binding constraint — a large monorepo will need chunking and a warm disk cache. Run frequency: analysis belongs in build/CI only. Never in a request path, never in a user-triggered job.
Failure modes.
Ramp-up. Low to first result — any Laravel developer gets output in an afternoon. Moderate-to-high to productionize: cache strategy, adapter, marker policy, golden tests, CI wiring, and an upgrade owner. Evaluate laravel/ranger first; if it supplies the high-level DTOs we need, it removes a meaningful chunk of that work.
How can I help you explore Laravel packages today?