hasProperty($propertyName)) { return $refl; } if (false === $parent = get_parent_class($class)) { // No more parents return null; } return self::getReflectionClassWithProperty($parent, $propertyName); } /** * Get an reflection property that you can access directly. * * @param object|string $objectOrClass * @param string $propertyName * * @return \ReflectionProperty * * @throws \InvalidArgumentException * @throws \LogicException if the property is not found on the object */ public static function getAccessibleReflectionProperty(object|string $objectOrClass, string $propertyName): \ReflectionProperty { $class = $objectOrClass; if (!is_string($objectOrClass)) { $class = get_class($objectOrClass); } if (null === $refl = static::getReflectionClassWithProperty($class, $propertyName)) { throw new \LogicException(sprintf('The property %s does not exist on %s or any of its parents.', $propertyName, $class)); } return $refl->getProperty($propertyName); } /** * Get a property of an object. If the property is static you may provide the class name (including namespace) * instead of an object. * * @param object|string $objectOrClass * @param string $propertyName * * @return mixed * * @throws \InvalidArgumentException * @throws \LogicException */ public static function getProperty(object|string $objectOrClass, string $propertyName): mixed { $reflectionProperty = static::getAccessibleReflectionProperty($objectOrClass, $propertyName); $object = $objectOrClass; if ($reflectionProperty->isStatic()) { $object = null; } elseif (is_string($objectOrClass)) { $object = (new \ReflectionClass($objectOrClass))->newInstanceWithoutConstructor(); } return $reflectionProperty->getValue($object); } /** * Set a property to an object. If the property is static you may provide the class name (including namespace) * instead of an object. * * @param object|string $objectOrClass * @param string $propertyName * @param mixed $value * * @throws \InvalidArgumentException * @throws \LogicException */ public static function setProperty(object|string $objectOrClass, string $propertyName, mixed $value): void { $reflectionProperty = static::getAccessibleReflectionProperty($objectOrClass, $propertyName); $object = $objectOrClass; if ($reflectionProperty->isStatic()) { $object = null; } elseif (is_string($objectOrClass)) { $object = (new \ReflectionClass($objectOrClass))->newInstanceWithoutConstructor(); } $reflectionProperty->setValue($object, $value); } /** * Get all property reflection objects of a class. * * @param object|string $objectOrClass * @return \ReflectionProperty[] of strings * @throws \InvalidArgumentException */ public static function getProperties(object|string $objectOrClass): array { $class = $objectOrClass; if (!is_string($objectOrClass)) { $class = get_class($objectOrClass); } $refl = new \ReflectionClass($class); $properties = $refl->getProperties(); // check parents while (false !== $parent = get_parent_class($class)) { $parentRefl = new \ReflectionClass($parent); $properties = array_merge($properties, $parentRefl->getProperties()); $class = $parent; } return $properties; } }