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

Phpdoc Reader Laravel Package

php-di/phpdoc-reader

PhpDocReader parses @var and @param docblock types to resolve class names, supporting fully qualified, imported, relative, and aliased names with the same rules as PHP. Primitive types are ignored; only valid class names are returned. Used by PHP-DI.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What it is: A ~300-line, single-responsibility library that takes a ReflectionProperty or ReflectionParameter, reads the associated docblock, parses @var/@param, and resolves the type token to a fully-qualified class name using PHP's own name-resolution rules (FQN, use imports, relative namespace, aliases). It returns null for primitives, scalars, arrays, and anything that isn't a resolvable class. It is explicitly not a general PHPDoc parser — no generics, no array shapes, no @method, no attribute reading.

Architecture fit: Narrow and well-bounded. The public surface is effectively two methods on one class, which makes it easy to wrap, stub, or replace. It fits cleanly as an inference adapter inside a dependency-injection container or a type-introspection layer — which is precisely its heritage: it exists to serve PHP-DI's autowiring. If our use case is "resolve constructor/property types from docblocks so a container can autowire untyped or legacy code," it is a direct fit. If our use case is broader static analysis, schema generation, or API documentation, it is underpowered and we would outgrow it immediately.

Integration feasibility: High. Composer-installable, MIT, no framework coupling, no service provider, no config. One use statement and a new PhpDocReader() and we are productive in an afternoon. The main gating check is the php constraint in composer.json versus our target runtime — the last tagged release is October 2020, so a PHP 8.3/8.4/8.5 runtime needs verification against CI rather than assumption (the repo does carry a GitHub Actions CI badge, which is a positive signal that it is not fully abandoned).

Technical risk: Moderate but contained.

Risk Severity Mitigation
Docblock reliance — opcache.save_comments=0 silently blanks every docblock, and the library degrades to "always null" rather than erroring High in prod Non-negotiable ini baseline + startup assertion
Source file must be readable and tokenizable (it parses use statements from the declaring file); eval'd, generated, or comment-stripped code fails Medium Compile-time only usage; never at request time
Heuristic scope — no generics, no unions, no ?Foo, no inline @var in method bodies Medium Document supported grammar; fall back to native reflection first
Single-maintainer, 74 stars, no release in ~5 years, dependents signal in our data shows 0 (contradicted by the README's PHP-DI/Zen users — treat the metric as unreliable and confirm on Packagist) Medium MIT + tiny surface = cheap fork; wrap behind our own interface
Returns null liberally with no diagnostic channel — failures are silent Medium Consumer-side null handling discipline and instrumentation

Key questions:

  1. What are the actual PHP version constraints and CI matrix? Does it pass on our target runtime, and is it tested against PHP 8.4 deprecations?
  2. Does it handle grouped use statements (use A\{B, C}), aliased imports, and use function/use const without mis-resolving?
  3. How does it treat union/nullable types (Foo|null, ?Foo, Foo&Bar)? Return the first, return null, or throw?
  4. Is the parsed file content cached per class, and is that cache safe to reuse across a long-running worker or only within a single compile?
  5. Is getPropertyClass/getParameterClass the intended stable API, or is there a newer entry point the README hasn't caught up to?
  6. For our specific need: could native reflection (typed properties, PHP 8 union/intersection types) plus a modern alternative — phpdocumentor/reflection-docblock, roave/better-reflection, or symfony/property-info — serve us with more headroom?

Integration Approach

Stack fit: Near-perfect for a Laravel shop that already leans on container autowiring and docblock-annotated service classes. Laravel's own container resolves via reflection on parameter types; this library fills the gap only where parameters are untyped and annotated, or where we are introspecting properties for custom resolution. Important framing: Laravel does not need this to function. This is only justified if we are (a) introducing PHP-DI alongside or instead of the Laravel container, (b) building an internal package that does docblock-driven autowiring, or (c) writing tooling that must read @param/@var class references. Absent one of those, the correct recommendation is do not adopt.

Migration path: Low-friction and reversible.

  1. composer require php-di/phpdoc-reader with an exact-pinned constraint (^1.4), committed lockfile.
  2. Wrap it immediately in a first-party interface, e.g. App\Introspection\DocblockTypeResolver, with resolvePropertyType() / resolveParameterType() returning a nullable string. Every call site depends on our interface, never on PhpDocReader directly. This is the whole exit strategy — if the package dies or proves too narrow, we swap the implementation for reflection-docblock and change one binding.
  3. Resolve native reflection types first, docblocks second. Never let a docblock override a declared type — that inverts PHP's own semantics and produces confusing container behaviour.
  4. Layer a caching decorator in front of the resolver keyed by class::member, populated during container/compile warm-up rather than per request.

Compatibility: No Laravel service provider, facade, or config to publish — register the binding manually in a service provider. Watch three environment assumptions: docblocks must survive to runtime (opcache.save_comments=1), source files must ship with the app (rules out some build-step stripping/minification pipelines), and the package's PHP constraint must admit our runtime. All three are checkable in a single CI job.

Sequencing:

  1. Spike (1–2 days): validate PHP constraint, grouped-use resolution, union/nullable handling, and opcache behaviour against a representative sample of our codebase. Measure how many @param/@var annotations actually resolve to a class — if the hit rate is low, kill the initiative here.
  2. Wrap: land the interface, the native-reflection-first resolver, and the caching decorator behind a feature flag.
  3. Instrument: log every null return with the declaring class and member; this is the only signal we will have that parsing silently failed.
  4. Baseline: add opcache.save_comments=1 to all environment configs and a boot-time guard that fails loudly if it is disabled.
  5. Prove: adopt in one internal package, run through a full release cycle, then widen.

Operational Impact

Maintenance: Effectively zero ongoing cost — the library has no dependencies, no configuration, no I/O beyond reading source files, and its behaviour is defined by PHP's name-resolution rules, which do not change. The flip side is that the dependency itself has no maintenance velocity: a five-year-old last release means an aging PHP compatibility surface and a maintainer who may not respond. Our wrapper interface converts that from a risk into a swap exercise, so the maintenance burden is really "maintain a 100-line adapter," not "maintain a library."

Support: Community-only, single primary maintainer, no commercial backing. Given the tiny code size and MIT licence, the realistic support model is fork-and-patch: if a PHP 8.x deprecation or a use-statement edge case bites us, we can vendor or fork and fix in hours. Budget for that possibility rather than treating upstream as an SLA.

Scaling: Parse cost is proportional to distinct reflected members and involves file reads plus tokenization, so it does not belong on the request path. Keep it in container compilation / build warm-up and cache aggressively. At that placement, scale impact is nil. If it ever leaks into per-request hot paths under load, the symptom will be unexpected filesystem reads in profiling rather than CPU burn — watch for that.

Failure modes (ranked by likelihood of surprising us in production):

  • Silent nulls under opcache.save_comments=0 — the highest-value guardrail. Everything works in dev, every docblock type vanishes in prod, and container resolution quietly falls back or throws an unhelpful "cannot resolve" error. Fail fast at boot.
  • Unresolvable annotations — typo'd class, class in a use group the parser doesn't handle, or a type that is really a generic (array<Foo>) and gets misread as a class named array<Foo>. Validate resolved names against class_exists before handing them to the container.
  • Missing source files — built artifacts that strip .php sources, or classes loaded from phar/eval contexts, cause resolution to fail or throw. Ensure container compilation happens where source is present.
  • Stale cache — if we cache resolved types keyed by member name and a class's use statements change without the class name changing, we serve a stale FQN. Invalidate on deploy, or key on file mtime in dev.
  • Semantic drift on PHP upgrades — a future PHP changing docblock availability or reflection comment behaviour. Low probability, trivial to detect with an integration test.

Ramp-up: Hours. Any PHP developer reads the README and is productive immediately; the API is two methods and the concept is familiar. The real onboarding cost is not the library but the policy around it — native types first, docblocks as fallback, resolve at compile time, assert opcache settings, instrument nulls. Put that in the wrapper's docblock and the team never needs to think about the underlying package again.

Verdict: Approve as a wrapped, compile-time-only, optional dependency, gated on the PHP-version check and a hit-rate spike — and only if we have a genuine docblock-driven autowiring or introspection requirement. Do not adopt it as general PHPDoc tooling; the grammar coverage is too thin and better-supported alternatives exist. Treat it as a small, replaceable adapter, not a platform commitment.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager