Created
March 12, 2025 17:47
-
-
Save DougallWinship/dc54431707de71f1884238ed874744c2 to your computer and use it in GitHub Desktop.
PHP trait (using magic methods and reflection) to interact with private attributes and methods in parent classes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait AccessPrivate { | |
private static $ancestorReflectionClasses = null; | |
private static function getAncestorReflectionClasses() | |
{ | |
if (is_null(self::$ancestorReflectionClasses)) { | |
$parentClasses = class_parents(self::class); | |
self::$ancestorReflectionClasses=[]; | |
foreach ($parentClasses as $parentClass) { | |
self::$ancestorReflectionClasses[] = new \ReflectionClass($parentClass); | |
} | |
} | |
return self::$ancestorReflectionClasses; | |
} | |
private static function findParentReflectProperty($property) | |
{ | |
$ancestorReflectionClasses = self::getAncestorReflectionClasses(); | |
foreach ($ancestorReflectionClasses as $ancestorReflectionClass) { | |
if ($ancestorReflectionClass->hasProperty($property)) { | |
return $ancestorReflectionClass->getProperty($property); | |
} | |
} | |
throw new \ReflectionException("Property '".$property."' does not exist as an attribute of ".self::class." or it's parents"); | |
} | |
private static function findParentReflectMethod($property) | |
{ | |
$ancestorReflectionClasses = self::getAncestorReflectionClasses(); | |
foreach ($ancestorReflectionClasses as $ancestorReflectionClass) { | |
if ($ancestorReflectionClass->hasMethod($property)) { | |
return $ancestorReflectionClass->getMethod($property); | |
} | |
} | |
throw new \ReflectionException("Property '".property."' does not exist as an method of ".self::class." or it's parents"); | |
} | |
public function __call($method, $args) | |
{ | |
$reflectMethod = self::findParentReflectMethod($method); | |
if ($reflectMethod->isPrivate()) { | |
$reflectMethod->setAccessible(true); | |
} | |
return $reflectMethod->invokeArgs($this, $args); | |
} | |
public function __get($name) | |
{ | |
$reflectProperty = self::findParentReflectProperty($name); | |
if ($reflectProperty->isPrivate()) { | |
$reflectProperty->setAccessible(true); | |
} | |
return $reflectProperty->getValue($this); | |
} | |
public function __set($name, $value) | |
{ | |
$reflectProperty = self::findParentReflectProperty($name); | |
if ($reflectProperty->isPrivate()) { | |
$reflectProperty->setAccessible(true); | |
} | |
return $reflectProperty->setValue($this,$value); | |
} | |
public static function __callStatic($name, $args) | |
{ | |
$reflectStaticMethod = self::findParentReflectMethod($name); | |
if ($reflectStaticMethod->isPrivate()) { | |
$reflectStaticMethod->setAccessible(true); | |
} | |
return $reflectStaticMethod->invokeArgs(null, $args); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment