我的方法的签名如下所示:
public function ProgramRuleFilter(&$program, $today=null) {
当我这样调用它时,
$programs = array_filter($programs, array($this,'ProgramRuleFilter'));
一切都按预期工作。 ProgramRuleFilter
方法更新$program
数组,如果成功则返回true / false,正确过滤$programs
。
但是,现在我想将一个额外的参数传递给过滤器$today
。我怎么能这样做?
我试图像这样调用它:
$programs = array_filter($programs, new CallbackArgs(array($this,'ProgramRuleFilter'),$today));
使用这个小类作为包装器:
class CallbackArgs {
private $callback;
private $args;
function __construct() {
$args = func_get_args();
$this->callback = array_shift($args);
$this->args = $args;
}
function __invoke(&$arg) {
return call_user_func_array($this->callback, array_merge(array($arg),$this->args));
}
}
但是程序没有被更新,所以在某个地方它失去了对原始对象的引用。我不知道如何解决这个问题。
答案 0 :(得分:9)
array_filter
的第二个参数必须是回调;这意味着array_filter
本身将调用您的过滤器功能。无法告诉array_filter
以任何其他方式调用该函数,因此您需要找到一种方法以某种方式将$today
的值放入您的函数中。
这是何时使用闭包的完美示例,它允许您将一些数据(在本例中为$today
的值)绑定到函数/回调中。假设您使用的是PHP 5.3或更高版本:
// Assuming $today has already been set
$object = $this; // PHP 5.4 eliminates the need for this
$programs = array_filter( $programs, function( $x ) use ( $today, $object ){
return $object->ProgramRuleFilter( $x, $today );
});
这使用来自父作用域的$today
和$object
的值来定义内联闭包,然后只调用该$对象上的现有函数ProgramRuleFilter
。 (有点不寻常的$object = $this
绕过这样的事实,否则,闭包将无法调用对象实例上的方法。但在PHP 5.4中,您可以用$object
替换$this
关闭内部。)
现在,这是一种有点不太优雅的方法,因为所有这些关闭都会将工作交给ProgramRuleFilter
函数。更好的方法是使用闭包而不是函数。所以:
// Assuming $today has already been set
$filter = function( $x ) use ( $today ){
// Cut and paste the contents of ProgramRuleFilter() here,
// and make it operate on $x and $today
};
$programs = array_filter( $programs, $filter );
哪种变体最适合您,取决于应用其余部分的实施情况。祝你好运!
答案 1 :(得分:1)
我写了一个新方法来处理它:
public static function array_filter_args($array, $callback) {
$args = array_slice(func_get_args(),2);
foreach($array as $key=>&$value) {
if(!call_user_func_array($callback, array_merge(array(&$value),$args))) {
unset($array[$key]);
}
}
return $array;
}
这样称呼:
$programs = ArrayHelper::array_filter_args($programs, array($this,'ProgramRuleFilter'), $today);
我不知道你能做到这一点array(&$value)
,但我想我会尝试一下,看起来它有效。我猜测array_merge
是导致该变量解除引用的罪魁祸首。