Skip to content

Instantly share code, notes, and snippets.

@funkatron
Created February 29, 2012 17:10
Show Gist options
  • Save funkatron/1942528 to your computer and use it in GitHub Desktop.
Save funkatron/1942528 to your computer and use it in GitHub Desktop.
Half-done features in PHP, pt 1
<?php
$app->foo = function() { echo 'test'; die;};
$app->foo(); // ERROR
$f = $app->foo;
$f(); // SUCCESS
/*********************************************************
Here's a modification to __call that would let you call
dynamically assigned methods in the normal fashion. This
is of limited uselfulness in PHP 5.3 because you can't
reference $this
**********************************************************/
<?php
class Foo
{
public function baz($txt) {
echo "BAZ: $txt\n";
}
public function __call($name, $arguments) {
if (isset($this->{$name}) && $this->{$name} instanceof Closure) {
$m = $this->{$name};
return call_user_func_array($m, $arguments);
}
}
}
$foo = new Foo();
$foo->bar = function($txt) { echo "BAR: $txt\n"; };
$foo->bar('This method was dynamically added');
$foo->baz('This method was defined in the class');
/*********************************************************
Here's a version for PHP 5.4 that binds the scope at
call time, letting us use $this within the Closure
**********************************************************/
trait Call_Dynamic_Methods {
public function __call($name, $arguments) {
if (isset($this->{$name}) && $this->{$name} instanceof Closure) {
$this->{$name} = $this->{$name}->bindTo($this, $this);
return call_user_func_array($this->{$name}, $arguments);
}
return parent::__call($name, $arguments);
}
}
class Foo54
{
use Call_Dynamic_Methods;
public $thing = 'blazzoooo';
public function baz($txt) {
echo "BAZ: $txt\n";
}
}
$foo = new Foo54();
$foo->baz('This method was defined in the class');
$foo->bar = function($txt) { echo "BAR: $txt\n"; };
$foo->bar('This method was dynamically added after instantiation');
$foo->bam = function($txt) { echo "BAM: $txt (" . $this->thing . ")\n"; };
$foo->bam('This method was dynamically added after instantiation, and references
$this. It will be bound at __call time to set the scope');
$flar = 'poop';
$foo->bal = function($txt) use ($flar) { echo "BAL: $txt (" . $this->thing . ") ($flar)\n"; };
$flar = 'poop2';
$foo->bal('This will output "poop" and not "poop2"');
@auroraeosrose
Copy link

Just for thoroughness - here's the technical reason in a nutshell - remember that properties and methods can have the same names in PHP classes https://gist.github.com/1951282

@funkatron
Copy link
Author

Appreciate your insights into it, Elizabeth. Ultimately, I think functional languages are a Big Win, and it's always a bummer to come up against the limitations in PHP related to functional programming. Actually making it happen in the existing runtime is, I'm sure, very non-trivial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment