Weave Code
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

Php Reflection Laravel Package

sajadsdi/php-reflection

Lightweight wrapper around PHP’s built-in Reflection API. Inspect classes by name or instance and quickly fetch ReflectionClass plus lists of properties, methods, and constants. Simple Reflections helper for common reflection tasks.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sajadsdi/php-reflection
    

    Ensure your project uses PHP 8.1+ (as per composer.json).

  2. First Use Case: Inspect a class's structure (e.g., methods, properties) without manually reading its code.

    use Sajadsdi\PhpReflection\Reflections;
    
    $reflector = new Reflections();
    $methods = $reflector->methods(\App\Models\User::class);
    
  3. Where to Look First:

    • Reflections class: Core entry point for all reflection operations.
    • Singleton Pattern: Use Reflections::getInstance() for performance-critical scenarios (e.g., repeated calls in a loop).
    • README.md: Quick-start examples for properties, methods, and constants.

Implementation Patterns

Common Workflows

  1. Dynamic Class Inspection:

    • Use Case: Generate API documentation or validation rules dynamically.
    $reflector = new Reflections();
    $properties = $reflector->properties(\App\DTO\RequestDTO::class);
    
    foreach ($properties as $property) {
        echo "Property: {$property->getName()}, Type: " . ($property->hasType() ? $property->getType()->getName() : 'mixed') . "\n";
    }
    
  2. Integration with Laravel:

    • Form Request Validation: Dynamically validate request data based on a model's properties.
      $rules = [];
      foreach ($reflector->properties(\App\Models\Post::class) as $property) {
          $rules[$property->getName()] = 'required|string';
      }
      return $rules;
      
    • Policy/Authorization: Check method existence or visibility for authorization logic.
      $method = $reflector->reflection(\App\Policies\PostPolicy::class)->getMethod('view');
      if ($method && $method->isPublic()) {
          // Grant access
      }
      
  3. Performance Optimization:

    • Caching Reflections: Store reflection results in a cache layer (e.g., Laravel's cache) to avoid repeated expensive operations.
      $cacheKey = 'reflection:App\Models\User';
      $reflection = cache()->remember($cacheKey, now()->addHours(1), function () use ($reflector) {
          return $reflector->reflection(\App\Models\User::class);
      });
      
  4. Event Listeners/Service Providers:

    • Bootstrap Reflection: Initialize the Reflections instance in a service provider's boot() method for global access.
      public function boot()
      {
          $this->app->singleton(Reflections::class, function () {
              return new Reflections();
          });
      }
      
  5. Testing:

    • Assert Class Structure: Verify class contracts or method signatures in PHPUnit tests.
      public function testUserModelHasEmailProperty()
      {
          $reflector = new Reflections();
          $property = $reflector->reflection(\App\Models\User::class)->getProperty('email');
          $this->assertTrue($property->isInitialized());
      }
      

Gotchas and Tips

Pitfalls

  1. Singleton Overhead:

    • Issue: While the singleton pattern improves performance, it may introduce global state issues if not managed carefully.
    • Fix: Use dependency injection (e.g., Laravel's container) instead of direct instantiation for better testability.
      // Avoid:
      $reflector = new Reflections();
      // Prefer:
      $reflector = app(Reflections::class);
      
  2. Reflection Limitations:

    • Issue: The package wraps PHP's native ReflectionClass, so it inherits limitations (e.g., private/protected members require ReflectionClass::newInstanceWithoutConstructor()).
    • Workaround: Use ReflectionClass directly for advanced use cases:
      $reflection = new \ReflectionClass(\App\Models\User::class);
      $privateProp = $reflection->getProperty('secret');
      $privateProp->setAccessible(true);
      
  3. PHP 8.1+ Only:

    • Issue: The package requires PHP 8.1+. Attempting to use it on older versions will fail.
    • Fix: Update your PHP version or use a polyfill like nikic/php-parser for reflection-like functionality.
  4. Circular Dependencies:

    • Issue: Reflecting classes with circular dependencies (e.g., A references B, which references A) may cause stack overflows.
    • Fix: Handle exceptions gracefully:
      try {
          $reflector->reflection(CircularClass::class);
      } catch (\ReflectionException $e) {
          // Fallback logic
      }
      
  5. Performance with Large Classes:

    • Issue: Reflecting classes with hundreds of methods/properties can be slow.
    • Fix: Cache results aggressively or use lazy loading:
      $reflector->methods(\App\Models\LargeModel::class, true); // Lazy loading (if supported)
      

Debugging Tips

  1. Verify Class Existence:

    • Ensure the class is autoloaded and the namespace is correct.
    if (!class_exists(\App\Models\User::class)) {
        throw new \RuntimeException('Class not found');
    }
    
  2. Check for Typos:

    • Method/property names are case-sensitive. Use getMethod() or getProperty() to validate existence:
    $method = $reflector->reflection(\App\Services\Logger::class)->getMethod('log');
    if (!$method) {
        throw new \InvalidArgumentException('Method not found');
    }
    
  3. Enable Reflection Exceptions:

    • Configure PHP to throw exceptions for invalid reflections (default in Laravel):
    ini_set('reflection.emitExceptions', 1);
    

Extension Points

  1. Custom Reflection Helpers:

    • Extend the Reflections class to add domain-specific methods:
    class ExtendedReflections extends Reflections {
        public function getTableName(string $class): string
        {
            $reflection = $this->reflection($class);
            return $reflection->getConstant('TABLE_NAME') ?? strtolower(class_basename($class));
        }
    }
    
  2. Integration with Laravel Scout:

    • Dynamically generate searchable attributes:
    public function toSearchableArray()
    {
        $reflector = new Reflections();
        $searchable = [];
        foreach ($reflector->properties(self::class) as $property) {
            if ($property->getName() !== 'created_at') {
                $searchable[$property->getName()] = $property->getValue($this);
            }
        }
        return $searchable;
    }
    
  3. Event-Based Reflection:

    • Trigger events when reflection results change (e.g., after model updates):
    event(new \App\Events\ReflectionUpdated(
        \App\Models\Post::class,
        $reflector->methods(\App\Models\Post::class)
    ));
    
  4. Mocking in Tests:

    • Use ReflectionClass::newInstanceWithoutConstructor() to mock private constructors:
    $reflection = new \ReflectionClass(\App\Services\PaymentGateway::class);
    $instance = $reflection->newInstanceWithoutConstructor();
    $instance->setTestMode(true);
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle