goaop/parser-reflection
Parser Reflection brings PHP's Reflection API to static analysis: parse source files into an AST and introspect classes, methods, and properties without autoloading, including, or executing code. Drop-in compatible with native Reflection classes for analyzers, generators, and IDE tooling.
goaop/parser-reflection is best treated as a development/static-analysis dependency, not a normal Laravel runtime package. It gives you ReflectionClass, ReflectionMethod, ReflectionProperty, ReflectionFile, etc. backed by source AST instead of loaded classes.
>=8.5 and nikic/php-parser:^5.9. Many Laravel apps are still on PHP 8.2–8.4, so Composer may resolve an older major. Verify that major against your Laravel/PHP version before adopting. For tooling-only use:
composer require --dev goaop/parser-reflection
Go\ParserReflection\LocatorInterface and pass it to ReflectionEngine::init().docs/reflection_file.md, docs/reflection_file_namespace.md, then the source for ReflectionClass, ReflectionEngine, and ComposerLocator.app/Models or app/Http/Controllers and report methods, properties, attributes, and docblocks.use Go\ParserReflection\ReflectionFile;
$file = new ReflectionFile(base_path('app/Models/User.php'));
foreach ($file->getFileNamespaces() as $namespace) {
foreach ($namespace->getClasses() as $class) {
$this->line($class->getName());
foreach ($class->getMethods() as $method) {
$this->line(' method: ' . $method->getName());
}
foreach ($class->getProperties() as $property) {
$this->line(' property: ' . $property->getName());
}
}
}
For known PSR-4 classes, new \Go\ParserReflection\ReflectionClass(\App\Models\User::class) works without instantiating User; using User::class does not load the class.
ReflectionFile is the reliable entry point for arbitrary files, generated code, or classes not yet resolvable through Composer. Iterate namespaces via getFileNamespaces(), then classes via getClasses().new \Go\ParserReflection\ReflectionClass($fqcn) is convenient when Composer can locate the file. It is the closest drop-in replacement for native \ReflectionClass.Controller; every public controller method has a return type; every model extends Model; jobs/events follow naming conventions; custom attributes are only used on supported targets. Run these in an Artisan command or CI job, not in request middleware.ReflectionClass instances.\ReflectionClass is expected. Parser reflection classes extend native reflection classes, so a service type-hinting \ReflectionClass can often accept them. Keep the boundary clear: metadata methods are safe; object-manipulation methods may trigger native fallback.getAttributes() lets you inspect Laravel/custom attributes without loading the class. On 5.x, named attribute arguments are keyed by name, matching native reflection. Only call newInstance() when you explicitly accept autoloading and attribute-constructor execution.LocatorInterface and initialize ReflectionEngine once in your bootstrap/tooling command.nikic/php-parser for AST details the reflection wrapper does not expose. Use parser reflection for the familiar reflection API; use raw AST nodes for precise syntax-level rules.Example architecture check:
use Go\ParserReflection\ReflectionClass;
$class = new ReflectionClass($fqcn);
foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
if ($method->getReturnType() === null) {
$this->warn("Missing return type: {$class->getName()}::{$method->getName()}");
}
}
>=8.5; Laravel projects on PHP 8.2–8.4 will need an older major. The package has a small adoption footprint in the supplied metadata, so pin it exactly, keep it dev-only, and have a fallback plan. If Composer conflicts with PHPStan, Rector, or another nikic/php-parser consumer, do not force it into the runtime dependency graph.ComposerLocator asks the Composer autoloader for a filename. New files may require composer dump-autoload; class aliases and anonymous classes are poor fits. If class-first reflection fails, switch to ReflectionFile on the actual path.invoke(), invokeArgs(), setAccessible(), and similar—can trigger native class loading and fallback. Once that happens, you are no longer in pure static-analysis mode.env(), config(), concatenation, or other expressions may not equal the runtime value. This matters for Laravel model $fillable, $casts, and config-driven properties. Treat getDefaultValue()/getDefaultProperties() as AST information, not application state.ReflectionExceptions. A single parse failure should not abort a directory scan. Log the file path, class name, and exception message, then continue.ReflectionException; scope-aware property readability resolves statically and deliberately does not autoload scope classes.ReflectionAttribute::getArguments(). If you are upgrading from 4.x, adjust code that assumed a positional list.ReflectionFile first. If new ReflectionClass($fqcn) fails, parse the expected file directly with ReflectionFile. If that works, the issue is class location/autoloading, not AST parsing. Check absolute paths and run composer dump-autoload -o when using optimized classmaps.vendor/, storage/, and generated cache directories.LocatorInterface, ReflectionEngine::init(), and composition around the reflection objects. For unsupported AST details, use nikic/php-parser directly rather than trying to patch behavior through Laravel config.How can I help you explore Laravel packages today?