Skip to content

Instantly share code, notes, and snippets.

@ezzatron
Created March 9, 2013 08:55
Show Gist options
  • Save ezzatron/5123547 to your computer and use it in GitHub Desktop.
Save ezzatron/5123547 to your computer and use it in GitHub Desktop.
Simple Liberator explanation
<?php
/**
* Firstly, some background information on reflection.
*
* Reflection is a way to find out information about objects, methods,
* functions, and other language constructs at runtime. In the case of PHP, it
* can also be used to change the behaviour of these constructs. One of the ways
* it can do this is to tell PHP to ignore 'private' and 'protected' access
* modifiers.
*
* There are different types of reflectors for different PHP constructs. The
* example below uses ReflectionObject and ReflectionMethod. ReflectionObject is
* used to create ReflectionMethod instances, and ReflectionMethod is used to
* ignore the 'private' access modifier.
*
* See http://php.net/manual/en/class.reflectionobject.php and
* http://php.net/manual/en/class.reflectionmethod.php for more information.
*/
/**
* This class will do the same kind of thing as eloquent/liberator.
*/
class SimpleLiberator
{
public function __construct($object)
{
// Here the object is stored for use later on when a method is called.
$this->object = $object;
// A new ReflectionObject is also created, as it will also be needed.
$this->reflector = new ReflectionObject($object);
}
/**
* This is a special PHP method. Any time a method is called on this object,
* and that method does not exist in the SimpleLiberator class, the name of
* the undefined method and the arguments are passed to __call(). See
* http://php.net/manual/en/language.oop5.overloading.php for more
* information.
*
* In the example below, this method gets called with $name = 'foo' and
* $arguments = array('a', 'b').
*/
public function __call($name, array $arguments)
{
// This creates a new ReflectionMethod for the method called $name on
// the $object stored in __construct().
$method = $this->reflector->getMethod($name);
// This makes PHP ignore the 'private' keyword, but only when the method
// is called using this ReflectionMethod instance.
// See http://php.net/manual/en/reflectionmethod.setaccessible.php for
// more information.
$method->setAccessible(true);
// This calls a method named $name on our original $object with
// $arguments, and returns the result.
return $method->invokeArgs($this->object, $arguments);
}
private $object;
private $reflector;
}
/**
* This is just an example class with a private method.
*/
class PrivateClass
{
private function foo($bar, $baz)
{
return sprintf("PrivateClass::foo() called with %s, %s\n", $bar, $baz);
}
}
/**
* Now for an example of how to use the classes above:
*/
// This is just a new instance of the 'PrivateClass' class above.
$privateObject = new PrivateClass;
// Here, a new liberator is created, and the new PrivateClass instance created
// above is passed to it.
$liberatorObject = new SimpleLiberator($privateObject);
// This will output 'PrivateClass::foo() called with a, b'
echo $liberatorObject->foo('a', 'b');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment