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

Reflection Laravel Package

skagarwal/reflection

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require skagarwal/reflection --dev
    
  2. Usage in Tests:

    • Import the ReflectableTrait in your test class (e.g., PHPUnit test case):
      use SKAgarwal\Reflection\ReflectableTrait;
      
      class UserTest extends \Tests\TestCase
      {
          use ReflectableTrait;
      }
      
  3. First Use Case:

    • Reflect a class instance in setUp() (for PHPUnit):
      protected function setUp(): void
      {
          $this->user = new \App\Models\User();
          $this->reflect($this->user);
      }
      
    • Test a private method:
      public function testPrivateMethod()
      {
          $result = $this->call('validateName', ['John Doe']);
          $this->assertTrue($result);
      }
      

Implementation Patterns

Core Workflows

  1. Reflecting a Single Class:

    • Use reflect() in setUp() for persistent reflection:
      $this->reflect(new \App\Services\PaymentService());
      
    • Chainable alternative: Use on() for one-off calls:
      $this->on(new \App\Services\PaymentService())
           ->call('processPayment', [$amount])
           ->get('transactionId');
      
  2. Testing Private/Protected Methods:

    • Dynamically call methods:
      $this->call('calculateTax', [$subtotal]);
      
    • Use method chaining for readability:
      $this->on($order)->callProcess()->get('total');
      
  3. Property Manipulation:

    • Get/set private properties:
      $this->set('isActive', true);
      $this->get('userId');
      
    • Dynamic syntax:
      $this->getUserId; // Equivalent to $this->get('userId')
      
  4. Multiple Classes in One Test:

    • Reflect multiple instances in setUp():
      $this->reflect($user = new \App\Models\User());
      $this->reflect($order = new \App\Models\Order());
      
    • Mix reflect() and on():
      $this->on(new \App\Services\Logger())->call('logError', [$message]);
      

Integration Tips

  • Laravel-Specific: Useful for testing Illuminate internals (e.g., Illuminate\Foundation\Application boot methods):
    $this->reflect(app());
    $this->call('bootProviders');
    
  • Service Containers: Test private container methods (e.g., Illuminate\Container\Container):
    $this->reflect(app)->call('make', ['App\Contracts\Service']);
    
  • Event Listeners: Test protected handle() methods:
    $this->reflect(new \App\Listeners\SendWelcomeEmail())
         ->call('handle', [$user]);
    

Gotchas and Tips

Pitfalls

  1. State Management:

    • reflect() persists the reflection for the class instance’s lifecycle. Avoid reflecting the same instance multiple times in setUp() if not needed.
    • on() creates a temporary reflection; changes won’t persist beyond the method call.
  2. Dynamic Method/Property Names:

    • Ensure method/property names match exactly (case-sensitive). Use IDE autocompletion to avoid typos:
      // ❌ Fails if method is `calculateTotal`
      $this->call('calculateTotalAmount');
      
  3. Static Methods/Properties:

    • The package does not support static reflection. Use ReflectionClass::newInstanceWithoutConstructor() or ::callStatic() as fallbacks.
  4. Closures/Lambdas:

    • Reflection fails on closures. Test their behavior via public interfaces instead.
  5. Performance:

    • Overusing on() for multiple calls on the same instance is less efficient than reflect(). Benchmark in CI:
      // Prefer this for repeated calls:
      $this->reflect($service);
      $this->call('methodA');
      $this->call('methodB');
      

Debugging

  • Invalid Method/Property Errors: Verify the class/method exists using:

    $this->assertMethodExists('App\Models\User', 'validateName');
    

    (Note: Requires custom assertion; use ReflectionClass directly if needed.)

  • Reflection Exceptions: Wrap calls in try-catch for graceful failures:

    try {
        $this->call('nonExistentMethod');
    } catch (\ReflectionException $e) {
        $this->fail($e->getMessage());
    }
    

Extension Points

  1. Custom Assertions: Extend PHPUnit with helper methods:

    protected function assertPrivateMethodReturns($instance, $method, $args, $expected)
    {
        $this->reflect($instance);
        $actual = $this->call($method, $args);
        $this->assertEquals($expected, $actual);
    }
    
  2. Mocking Reflection: For isolated tests, mock the trait’s methods:

    $this->getMockBuilder(SKAgarwal\Reflection\ReflectableTrait::class)
         ->onlyMethods(['call'])
         ->getMock();
    
  3. Laravel Artisan Commands: Test protected handle() methods:

    $this->reflect(Artisan::getInstance())
         ->call('fire', ['command:key:generate']);
    

Config Quirks

  • PHP Version: Requires PHP ≥5.4.0. Test on older versions (e.g., Laravel 5.1) may fail due to Reflection API changes.
  • Autoloading: Ensure the trait is autoloaded in composer.json:
    "autoload": {
        "psr-4": {
            "SKAgarwal\\Reflection\\": "vendor/skagarwal/reflection/src"
        }
    }
    
    Run composer dump-autoload if issues arise.

Maintenance Tips

  • Archived Package: Fork the repo to apply fixes (e.g., PHP 8 compatibility) if needed. Key files:
    • src/ReflectableTrait.php (core logic)
    • tests/ (test patterns for extension).
  • Alternatives: For modern Laravel, consider mockery or phpunit/phpunit's built-in reflection tools:
    $reflection = new \ReflectionMethod($class, 'privateMethod');
    $reflection->setAccessible(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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky