PHP code example of kariricode / property-inspector

1. Go to this page and download the library: Download kariricode/property-inspector library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

kariricode / property-inspector example snippets


// The old way: raw reflection on every request
$ref = new ReflectionClass($user);
foreach ($ref->getProperties() as $prop) {
    $attrs = $prop->getAttributes(Validate::class);
    foreach ($attrs as $attr) {
        $prop->setAccessible(true); // deprecated in PHP 8.4
        $value = $prop->getValue($user);
        // now what? where does the result go? how do you write it back?
    }
}

use KaririCode\PropertyInspector\AttributeAnalyzer;
use KaririCode\PropertyInspector\Utility\PropertyInspector;
use KaririCode\PropertyInspector\Utility\PropertyAccessor;

// 1. Configure which attribute to scan for
$analyzer  = new AttributeAnalyzer(Validate::class);
$inspector = new PropertyInspector($analyzer);

// 2. Inspect — results cached after first call per class
$handler = new MyValidationHandler();
$inspector->inspect($user, $handler);

// 3. Read processed values and errors
$values = $handler->getProcessedPropertyValues();
$errors = $handler->getProcessingResultErrors();

// 4. Write back changed values via PropertyAccessor
$accessor = new PropertyAccessor($user, 'email');
$accessor->setValue(strtolower($accessor->getValue()));



declare(strict_types=1);

ropertyInspector\AttributeAnalyzer;
use KaririCode\PropertyInspector\Contract\PropertyAttributeHandler;
use KaririCode\PropertyInspector\Utility\PropertyInspector;

// 1. Define a custom attribute
#[Attribute(Attribute::TARGET_PROPERTY)]
final class Validate
{
    public function __construct(public readonly array $rules = []) {}
}

// 2. Define an entity with annotated properties
final class User
{
    public function __construct(
        #[Validate(['ssed[$propertyName] = $value;

        if ($attribute instanceof Validate) {
            foreach ($attribute->rules as $rule) {
                if ($rule === 'ction getProcessedPropertyValues(): array { return $this->processed; }
    public function getProcessingResultMessages(): array { return []; }
    public function getProcessingResultErrors(): array   { return $this->errors; }
}

// 4. Run the pipeline
$user      = new User(name: 'Walmir', email: '[email protected]', age: 30);
$analyzer  = new AttributeAnalyzer(Validate::class);
$inspector = new PropertyInspector($analyzer);
$handler   = new ValidationHandler();

$inspector->inspect($user, $handler);

var_dump($handler->getProcessedPropertyValues());
// ['name' => 'Walmir', 'email' => '[email protected]', 'age' => 30]

var_dump($handler->getProcessingResultErrors());
// [] — all good

$analyzer = new AttributeAnalyzer(Validate::class);
$inspector = new PropertyInspector($analyzer);

// First call: reflection + cache build
$inspector->inspect($user1, $handler1);

// Subsequent calls: metadata from cache — zero reflection overhead
$inspector->inspect($user2, $handler2);
$inspector->inspect($user3, $handler3);

// Force re-analysis when needed (e.g., after metadata change)
$analyzer->clearCache();

// Pass 1: sanitize
$sanitizeInspector = new PropertyInspector(new AttributeAnalyzer(Sanitize::class));
$sanitizeHandler   = new TrimLowercaseHandler();
$sanitizeInspector->inspect($user, $sanitizeHandler);

// Apply sanitized values back to the object
foreach ($sanitizeHandler->getProcessedPropertyValues() as $prop => $value) {
    (new PropertyAccessor($user, $prop))->setValue($value);
}

// Pass 2: validate on sanitized data
$validateInspector = new PropertyInspector(new AttributeAnalyzer(Validate::class));
$validateHandler   = new ValidationHandler();
$validateInspector->inspect($user, $validateHandler);

$errors = $validateHandler->getProcessingResultErrors(); // [] if clean

use KaririCode\PropertyInspector\Utility\PropertyAccessor;

$accessor = new PropertyAccessor($user, 'email');

$current = $accessor->getValue();           // read
$accessor->setValue(strtolower($current));  // write (no setAccessible needed)

// Matches Validate + any subclass of Validate
$analyzer = new AttributeAnalyzer(Validate::class);

use KaririCode\PropertyInspector\Exception\PropertyInspectionException;

try {
    $inspector->inspect($user, $handler);
} catch (PropertyInspectionException $e) {
    // ReflectionException, TypeError, Error — all caught and re-wrapped
}

$inspector->inspect($object, $handler)
        │
        ▼
AttributeAnalyzer::analyzeObject($object)
  ├── Check class cache
  ├── If miss: ReflectionClass → getProperties()
  │       └── foreach property:
  │               getAttributes($attributeClass, IS_INSTANCEOF)
  │               newInstance() → cache [{attributes, property}]
  └── extractValues($object): [{value, attributes}]
        │
        ▼
foreach property → foreach attribute:
    $handler->handleAttribute($propertyName, $attribute, $value)
        │
        ▼
return $handler  (accumulates processed values + errors)

src/
├── AttributeAnalyzer.php      Core analyzer — reflection + cache + attribute extraction
├── Contract/
│   ├── AttributeAnalyzer.php       Interface: analyzeObject · clearCache
│   ├── PropertyAttributeHandler.php Interface: handleAttribute · getProcessed* · getErrors
│   ├── PropertyChangeApplier.php   Interface: applyChanges
│   └── PropertyInspector.php       Interface: inspect
├── Exception/
│   └── PropertyInspectionException.php  Named factory methods per failure mode
└── Utility/
    ├── PropertyAccessor.php   Safe property read/write (private, protected, public)
    └── PropertyInspector.php  Orchestrator: delegates analysis → handler