Created
March 9, 2013 08:55
-
-
Save ezzatron/5123547 to your computer and use it in GitHub Desktop.
Simple Liberator explanation
This file contains 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
<?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