Skip to content

Instantly share code, notes, and snippets.

@zburgermeiszter
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zburgermeiszter/13e1515b2dae86a41933 to your computer and use it in GitHub Desktop.
Save zburgermeiszter/13e1515b2dae86a41933 to your computer and use it in GitHub Desktop.
Access $this from Closure
<?php
/**
* In PHP 5.3 you can't access $this from anonymous functions, even if you inject $this to them, you still can't access private functions.
* Here's the workaround. With this you can inject $this to anonymous function and after calling publishPrivate()
* You'll be able to call private member functions when you need.
* All of them would't be needed in PHP 5.4 (but fortunately compatible with php 5.4 :)
*/
var_dump(phpversion());
class C
{
private $publicPrivate = false;
public function publishPrivate()
{
$this->publicPrivate = true;
return $this;
}
private function func()
{
return "Private result";
}
/**
* PHP Magic method override to expose private methods.
* @param $name
* @param $arguments
* @return bool|mixed
*/
public function __call($name, $arguments)
{
$ro = new \ReflectionObject($this);
$methodExists = $ro->hasMethod($name);
if ($methodExists) {
$rm = new \ReflectionMethod($this, $name);
} else {
return false;
}
$callablePublic = $methodExists && is_callable(array($this, $name)) && !$rm->isPrivate() && !$rm->isProtected();
$callablePrivate = $methodExists && $this->publicPrivate;
$callable = $callablePublic || $callablePrivate;
if ($callable) {
$this->publicPrivate = false; // unpublish private (!)
return call_user_func_array(array($this, $name), $arguments);
} else {
return new FatalErrorException("Error: Call to private method " . $name . "()");
}
}
/**
* PHP magic method override to expose private properties.
* @param $name
* @throws FatalErrorException
* @return bool|mixed
*/
public function __get($name)
{
$ro = new \ReflectionObject($this);
$propertyExists = $ro->hasProperty($name);
if ($propertyExists) {
$rp = new \ReflectionProperty($this, $name);
} else {
return false;
}
$propertyPublic = $propertyExists && !$rp->isPrivate() && !$rp->isProtected();
$propertyPrivate = $propertyExists && $this->publicPrivate;
$accessible = $propertyPublic || $propertyPrivate;
if ($accessible) {
$this->publicPrivate = false; // unpublish private (!)
return $this->$name;
} else {
throw new FatalErrorException("Error: Cannot access private property $" . $name);
}
}
public function callPrivateFunctionFromClosure()
{
$self = $this; // Force inject $this
$callPrivate = function() use ($self)
{
return $self->publishPrivate()->func();
};
return $callPrivate();
}
}
$c = new C();
echo $c->callPrivateFunctionFromClosure();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment