備忘録 @ ウィキ
bind
最終更新:
mlnk
-
view
関数の引数を束縛する
STLのbind1st、bind2ndみたいな。
使いどころ
- array_mapとかに toStringの代わりにvar_exportでもいいかもしれない。循環参照があったらだめだけど。
class Binder_Argument {};
function& Argument()
{
static $obj = null;
if(is_null($obj)) {
$obj = new Binder_Argument;
}
return $obj;
}
function toString($a)
{
$ret = $a;
if(is_string($a)) {
$ret = "'".$a."'";
} else if(is_array($a)) {
$content = array();
foreach($a as $k=>$v) {
$content[] = toString($k).'=>'.toString($v);
}
$ret = 'array('.implode(', ', $content).')';
} else if(is_bool($a)) {
$ret = ($a?'true':'false');
} else if(is_null($a)) {
$ret = 'null';
} else if(is_object($a)) {
$ret = 'unserialize(\''.serialize($a).'\')';
}
return $ret;
}
function bind($func)
{
$num_args = func_num_args();
$comp_obj = Argument();
$args = array();
$arg_for_code = array();
for($i=1; $i<$num_args; ++$i) {
$arg = func_get_arg($i);
if($arg===$comp_obj) {
$count = count($args);
$arg_for_code[] = "\$arg{$count}";
$args[] = "\$arg{$count}";
} else {
$arg_for_code[] = toString($arg);
}
}
$args = implode(', ', $args);
if(is_array($func) && is_object($func[0])) {
$code = 'static $o = null; '
.'if(is_null($o)){'
.'$o=unserialize(\''.str_replace("'", "\\'", serialize($func[0])).'\');'
.'}'
.'return call_user_func(array($o, '.toString($func[1]).')';
} else {
$code = 'return call_user_func('.toString($func);
}
$code .= ', '.implode(', ', $arg_for_code).');';
return create_function($args, $code);
}
使い方
固定したくない引数にArgument()を指定する。
function func($a, $b) {
echo "{$a}-{$b}";
}
class obj {
var $c;
function obj($c) {
$this->c = $c;
}
function func2($a, $b) {
echo "static: {$a}-{$b}";
}
function func3($a, $b) {
echo "class: {$a}-{$b}-{$this->c}";
}
}
$f = bind('func', Argument(), 'bar');
$f('foo'); // foo-bar
$f = bind(array('obj', 'func2'), 'bar');
$f('foo'); // static: foo-bar
$o = new obj('bazz');
$f = bind(array($o, 'func3'), 'bar');
$f('foo'); // class: foo-bar-bazz