将额外参数传递给 usort 回调

2022-08-30 11:05:16

我有以下功能。WordPress功能,但这实际上是一个PHP问题。它们根据每个对象元数据中的属性对对象进行排序。$termartist_lastname

我想在第一个函数中传递一个字符串。这将允许我重用此代码,因为我可以将其应用于各种元数据属性。$meta

但是我不明白如何将额外的参数传递给usort回调。我试图制作一个JS风格的匿名函数,但服务器上的PHP版本太旧了(v. 5.2.17),并抛出了语法错误。

任何帮助 - 或推向手册的右下角 - 非常感谢。谢谢!

function sort_by_term_meta($terms, $meta) 
{
  usort($terms,"term_meta_cmp");
}

function term_meta_cmp( $a, $b ) 
{
    $name_a = get_term_meta($a->term_id, 'artist_lastname', true);
    $name_b = get_term_meta($b->term_id, 'artist_lastname', true);
    return strcmp($name_a, $name_b); 
}

PHP 版本: 5.2.17


答案 1

我认为这个问题值得更新。我知道最初的问题是针对PHP版本5.2的,但是我来这里寻找解决方案,并为较新版本的PHP找到了一个解决方案,并认为这可能对其他人有用。

对于 PHP 5.3 及更高版本,您可以使用 'use' 关键字将局部变量引入匿名函数的局部作用域。因此,以下内容应该有效:

function sort_by_term_meta(&$terms, $meta) {
    usort($terms, function($a, $b) use ($meta) {
        $name_a = get_term_meta($a->term_id, 'artist_lastname', true);
        $name_b = get_term_meta($b->term_id, 'artist_lastname', true);
        return strcmp($name_a, $name_b);  
    });
}

一些更通用的代码

如果你想对数组只排序一次,并且需要一个额外的参数,你可以使用一个匿名函数,如下所示:

usort($arrayToSort, function($a, $b) use ($myExtraArgument) {
    //$myExtraArgument is available in this scope
    //perform sorting, return -1, 0, 1
    return strcmp($a, $b);
});

如果您需要一个可重用的函数来对需要额外参数的数组进行排序,则始终可以包装匿名函数,就像原始问题一样:

function mySortFunction(&$arrayToSort, $myExtraArgument1, $myExtraArgument2) {
    usort($arrayToSort, function($a, $b) use ($myExtraArgument1, $myExtraArgument2) {
        //$myExtraArgument1 and 2 are available in this scope
        //perform sorting, return -1, 0, 1
        return strcmp($a, $b);
    });
}

答案 2

在 PHP 中,回调的一个选项是传递一个包含对象句柄和要调用对象的方法名称的双元素数组。例如,如果 是 类 的一个实例,并且您想要调用 on 的方法,则可以作为回调传递。$objMyCallablemethod1MyCallable$objarray($obj, "method1")

使用此受支持的回调类型的一种解决方案是定义一个基本类似于闭包类型的一次性类:

function sort_by_term_meta( $terms, $meta ) 
{
    usort($terms, array(new TermMetaCmpClosure($meta), "call"));
}

function term_meta_cmp( $a, $b, $meta )
{
    $name_a = get_term_meta($a->term_id, $meta, true);
    $name_b = get_term_meta($b->term_id, $meta, true);
    return strcmp($name_a, $name_b); 
} 

class TermMetaCmpClosure
{
    private $meta;

    function __construct( $meta ) {
        $this->meta = $meta;
    }

    function call( $a, $b ) {
        return term_meta_cmp($a, $b, $this->meta);
    }
}

推荐