Created
February 29, 2012 17:10
-
-
Save funkatron/1942528 to your computer and use it in GitHub Desktop.
Half-done features in PHP, pt 1
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 | |
$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"'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.