PEP 309 のパクリ
<?php function partial($func, $params, $append = false) { if (!is_callable($func, false, $callable)) { trigger_error("$callable is not a valid function", E_USER_WARNING); return false; } if (!isset($GLOBALS['__PARTIAL_FUNCTION'])) { $GLOBALS['__PARTIAL_FUNCTION'] = array(); } $n = count($GLOBALS['__PARTIAL_FUNCTION']); $GLOBALS['__PARTIAL_FUNCTION'][$n] = array($func); $GLOBALS['__PARTIAL_FUNCTION'][$n][] = is_array($params) ? $params : array($params); if ($append) { return create_function('', '$params = func_get_args(); return call_user_func_array( $GLOBALS["__PARTIAL_FUNCTION"][' . $n . '][0], array_merge($params, $GLOBALS["__PARTIAL_FUNCTION"][' . $n . '][1]) );' ); } else { return create_function('', '$params = func_get_args(); return call_user_func_array( $GLOBALS["__PARTIAL_FUNCTION"][' . $n . '][0], array_merge($GLOBALS["__PARTIAL_FUNCTION"][' . $n . '][1], $params) );' ); } } if (isset($_SERVER['argv']) && realpath($_SERVER['argv'][0]) == __FILE__) { $log2 = partial('log', 2, true); var_dump($log2(256), log(256, 2)); }
PHP5 用にアレンジ
<?php class Partial { private $_prefix; private $_params; private $_append; public function __construct($prefix, $params, $append = false) { if (is_object($prefix)) { $this->_prefix = array($prefix); } elseif (!is_string($prefix)) { throw new Exception('Argument #1 should be an object or a string'); } elseif (!strlen($prefix)) { $this->_prefix = ''; } elseif (!preg_match('/^([A-Za-z_]?w*)(::)?$/', $prefix, $matches)) { throw new Exception("{$prefix} is not a valid function name prefix"); } elseif (!empty($matches[2])) { if (!class_exists($matches[1])) { throw new Exception("Class {$matches[1]} does not exist"); } $this->_prefix = array($matches[1]); } else { $this->_prefix = $prefix; } $this->_params = is_array($params) ? $params : array($params); $this->_append = (bool)$append; } public function __call($name, $args) { if (is_array($this->_prefix)) { $func = $this->_prefix; $func[] = $name; } else { $func = $this->_prefix . $name; } if (!is_callable($func, false, $callable)) { trigger_error("$callable is not callable", E_USER_WARNING); return; } if ($this->_append) { $args = array_merge($args, $this->_params); } else { $args = array_merge($this->_params, $args); } return call_user_func_array($func, $args); } }
たとえばイメージ関数を OO ライクに使ったりできるようになります。
<?php $rsrc = imagecreatetruecolor(120, 30); if (!$rsrc) { exit; } $img = new Partial('image', $rsrc); $white = $img->colorAllocate(255, 255, 255); $black = $img->colorAllocate(0, 0, 0); $img->fill(0, 0, $white); $img->string(3, 5, 5, 'Hello, Partial!', $black); $out = 'hello-partial.png'; if (file_exists($out)) { die("$out already exists"); } $img->png($out, 9, PNG_ALL_FILTERS);
追記:
(array)$params
は $params が null またはオブジェクトのとき想定外の挙動になるので、
該当箇所を is_array($params) ? $params : array($params)
と修正しました。