goaop/parser-reflection

Provides reflection information, based on raw source

Maintainers

Package info

github.com/goaop/parser-reflection

pkg:composer/goaop/parser-reflection

Fund package maintenance!

lisachenko

Statistics

Installs: 3 413 404

Dependents: 9

Suggesters: 0

Stars: 100

Open Issues: 9

4.0.0-RC2 2024-03-18 21:43 UTC

README

๐Ÿ” Static Code Analysis Meets Reflection

Parser Reflection API brings the power of PHP's Reflection API to static code analysis. Built on top of nikic/php-parser, this library lets you introspect classes, methods, and properties without ever loading them into memory.

โœจ Key Features

๐Ÿง  Pure AST-Based Reflection

Forget autoloading. This library parses your PHP source files directly into an Abstract Syntax Tree (AST) and extracts reflection data from the syntax itself โ€” no include, no require, no side effects. Analyze classes without bootstrapping your entire application. Perfect for static analyzers, code generators, documentation tools, and IDE plugins.

Why Use It?

  • ๐Ÿ“Š Source code analysis โ€” inspect structure without executing anything
  • ๐Ÿงช Safe introspection โ€” avoid triggering constructors or static initializers
  • ๐Ÿ”Œ Drop-in compatible โ€” extends native \ReflectionClass, \ReflectionMethod, etc.

GitHub Workflow Status PHPStan Badge GitHub release Total Downloads Daily Downloads PHP Version License Sponsor

Installation

Library can be installed with Composer. Installation is quite easy:

$ composer require goaop/parser-reflection

Composer will install the library to your project's vendor/goaop/parser-reflection directory.

Usage

Initialization

Prior to the first use library can be optionally initialized. If you use Composer for installing packages and loading classes, then you shouldn't worry about initialization, library will be initialized automatically.

If project uses a custom autoloader then you should follow the next steps:

  1. Create a new class that implements \Go\ParserReflection\LocatorInterface
  2. Create an instance of that class and pass it to the ReflectionEngine::init() method for initial configuration

Reflecting concrete classes/methods/properties without loading them

Just use Go\ParserReflection package reflection classes like traditional ones:

$parsedClass = new \Go\ParserReflection\ReflectionClass(SomeClass::class);
var_dump($parsedClass->getMethods());

$parsedMethod = new \Go\ParserReflection\ReflectionMethod(SomeClass::class, 'someMethod');
echo (string)$parsedMethod;

Or you can use an additional classes ReflectionFile and ReflectionFileNamespace to analyse a raw PHP files:

$parsedFile     = new \Go\ParserReflection\ReflectionFile('SomeClass.php');
$fileNameSpaces = $parsedFile->getFileNamespaces();
// We can iterate over namespaces in the file
foreach ($fileNameSpaces as $namespace) {
    $classes = $namespace->getClasses();
    // Iterate over the classes in the namespace
    foreach ($classes as $class) {
        echo "Found class: ", $class->getName(), PHP_EOL;
        // Now let's show all methods in the class
        foreach ($class->getMethods() as $method) {
            echo "Found class method: ", $class->getName(), '::', $method->getName(), PHP_EOL;
        }
        
        // ...all properties in the class
        foreach ($class->getProperties() as $property) {
            echo "Found class property: ", $class->getName(), '->', $property->getName(), PHP_EOL;
        }
    }
}

How it works?

To understand how library works let's look at what happens during the call to the new \Go\ParserReflection\ReflectionClass(SomeClass::class)

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   ReflectionClass   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚ asks for AST node
           โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ReflectionEngine   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚ locates file
           โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ComposerLocator    โ”‚ โ”€โ”€โ–บ Composer autoloader
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚ parses file
           โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  nikic/php-parser   โ”‚ โ”€โ”€โ–บ Returns AST
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚ wraps nodes
           โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Reflection Objects โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • \Go\ParserReflection\ReflectionClass asks reflection engine to give an AST node for the given class name
  • Reflection engine asks a locator to locate a filename for the given class
  • ComposerLocator instance asks the Composer to find a filename for the given class and returns this result back to the reflection engine
  • Reflection engine loads the content of file and passes it to the PHP-Parser for tokenization and processing
  • PHP-Parser returns an AST (Abstract Syntax Tree)
  • Reflection engine then analyse this AST to extract specific nodes and wrap them into corresponding reflection classes.

Compatibility

All parser reflection classes extend PHP internal reflection classes, this means that you can use \Go\ParserReflection\ReflectionClass instance in any place that asks for \ReflectionClass instance. All reflection methods should be compatible with original ones, providing an except methods that requires object manipulation, such as invoke(), invokeArgs(), setAccessible(), etc. These methods will trigger the process of class loading and switching to the internal reflection.