问题描述

我有以下功能 Wordpress 功能,但这是一个 PHP 问题。他们根据每个对象的元数据中的 artist_lastname 属性对 $term 对象进行排序。

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

但是我不知道如何传递额外的参数到 usort 回调。我试图制作一个 JS 风格的匿名函数,但是服务器上的 PHP 版本太旧了,并发出语法错误。

任何帮助 – 或者向手册右侧的一个方向感谢。谢谢!

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 中,callback 的一个选项是传递一个包含对象句柄和方法名称的 two-element 数组,以调用该对象。例如,如果 $ obj 是 MyCallable 类的一个实例,并且您要调用 $ obj 上的 MyCallable 的 method1 方法,那么可以将数组 ($ obj,”method1″) 作为回调传递。

使用这种支持的回调类型的一个解决方案是定义一个基本上类似于闭包类型的 single-use 类:

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);
    }
}

次佳解决方法

我认为这个问题值得更新。我知道原来的问题是 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);
    });
}

第三种解决方法

假设您访问对象和静态 (PHP 5 或更高版本),您可以创建一个对象并直接传递参数,如下所示:

<?php
class SortWithMeta {
    private static $meta;

    static function sort(&$terms, $meta) {
       self::$meta = $meta;
       usort($terms, array("SortWithMeta", "cmp_method"));
    }

    static function cmp_method($a, $b) {
       $meta = self::$meta; //access meta data
       // do comparison here
    }

}

// then call it
SortWithMeta::sort($terms, array('hello'));

假设你没有访问对象/static; 你可以做一个全球化:

$meta = array('hello'); //define meta in global

function term_meta_cmp($a, $b) {
   global $meta; //access meta data
   // do comparison here
}

usort($terms, 'term_meta_cmp');

第四种方法

该文档说,create_function()应该在 PHP> = 4.0.1 上工作。这是否有效?

function term_meta_cmp( $a, $b, $meta )  {
    echo "$a, $b, $meta<hr>"; // Debugging output
}
$terms = array("d","c","b","a");
usort($terms, create_function('$a, $b', 'return term_meta_cmp($a, $b, "some-meta");'));

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。