Skip to content

Instantly share code, notes, and snippets.

@jkrzefski
Last active May 24, 2018 12:33
Show Gist options
  • Save jkrzefski/a22402bbe45b6035c32ad445e1d623ac to your computer and use it in GitHub Desktop.
Save jkrzefski/a22402bbe45b6035c32ad445e1d623ac to your computer and use it in GitHub Desktop.
This "hack" grants external callers read-, write- and execution-access to private and protected members of an instance. Beware that this violates the idea of oop and should therefore only be the last resort before giving up.
<?php
use Closure;
use Exception;
use ReflectionException;
use ReflectionMethod;
/**
* Class AccessEnforcer
*/
class AccessEnforcer
{
/**
* Reads a private attribute of the given
* instance. Cannot read private attributes
* of any parent classes.
*
* @param $instance
* @param $name
* @return mixed
* @throws Exception
*/
public static function forceRead($instance, $name)
{
if (!is_object($instance)) {
throw new Exception('$instance must be an object.');
}
$spoof = Closure::bind(function ($instance) use ($name) {
return $instance->{$name};
}, null, $instance);
return $spoof($instance);
}
/**
* Writes a value to a specific private
* attribute of the given instance.
* Cannot override private attributes of
* any parent classes.
*
* @param $instance
* @param $name
* @param $value
* @throws Exception
*/
public static function forceWrite($instance, $name, $value)
{
if (!is_object($instance)) {
throw new Exception('$instance must be an object.');
}
$spoof = Closure::bind(function ($instance) use ($name, $value) {
$instance->{$name} = $value;
}, null, $instance);
$spoof($instance);
}
/**
* Calls a private method of the given
* instance with the given parameters
* and returns its return value.
*
* @param $instance
* @param $name
* @param array ...$arguments
* @return mixed
* @throws Exception
* @throws ReflectionException
*/
public static function forceCallMethod($instance, $name, ...$arguments)
{
if (!is_object($instance)) {
throw new Exception('$instance must be an object.');
}
$method = new ReflectionMethod(get_class($instance), $name);
$method->setAccessible(true);
return $method->invoke($instance, ...$arguments);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment