sebastian/object-reflector
Reflect object properties across a class hierarchy, including inherited, private, and protected members. sebastian/object-reflector provides a small utility for accessing and inspecting object state when PHP’s standard reflection APIs are inconvenient.
Install the package as a dev dependency to avoid runtime overhead:
composer require --dev sebastian/object-reflector
Begin by inspecting private/protected properties in tests or debugging sessions. The API is minimal and self-explanatory:
use SebastianBergmann\ObjectReflector\ObjectReflector;
$reflector = new ObjectReflector();
$properties = $reflector->getProperties($someObject);
// Output all properties and their values
foreach ($properties as $name => $value) {
echo "$name = " . print_r($value, true) . PHP_EOL;
}
This is your go-to when Laravel’s dump(), dd(), or even Illuminate\Support\Debug\Dumper can’t peek inside private properties — especially in legacy code or deeply nested service objects.
@access annotations or reflection boilerplate in PHPUnit tests. For example, assert internal state of a repository or domain service without violating encapsulation:
$order = new Order($items);
$reflector = new ObjectReflector();
$this->assertSame(OrderStatus::CONFIRMED, $reflector->getProperties($order)['status']);
__toString() for Logging: Implement clean debug output in domain models:
public function __toString(): string
{
$reflector = new ObjectReflector();
$props = $reflector->getProperties($this);
return get_class($this) . '(' . implode(', ', array_map(
fn($k, $v) => "$k=" . (is_object($v) ? get_class($v) : $v),
array_keys($props), $props
)) . ')';
}
function dump_private(object $object): void
{
$props = (new ObjectReflector)->getProperties($object);
dump($props);
}
Then call dump_private($user) to see all inherited properties — even private ones from UserTrait or parent classes.composer show sebastian/object-reflector and compare to php -v. Out-of-sync versions cause silent failures or BC breaks in tests.ParentClass::property. This avoids ambiguity but breaks naive string matching — e.g., User::id vs Model::id. Use explode('::', $key) to extract class and property parts.readonly properties, but cannot modify them. Don’t attempt to use ReflectionProperty::setValue() — this package only reads.APP_ENV=testing or APP_DEBUG=true. Add a guard:
if (app()->environment('local', 'testing')) {
// Use ObjectReflector
}
getProperties() returns all properties across the entire chain — including private ones hidden in deeply nested traits or abstract parents. This is powerful for debugging but may surprise if you expect only declared properties.final, so no subclassing. Build your own abstraction (e.g., App\Support\PropertyInspector) to insulate app code from direct dependency use.print_r() may fail or expose sensitive data. Sanitize before logging.How can I help you explore Laravel packages today?