54

我有一个对多维数组中的数据进行排序的函数,如下所示:

<?php  
$data = array();  
$data[] = array("name" => "James");  
$data[] = array("name" => "andrew");  
$data[] = array("name" => "Fred");  

function cmp($a, $b)  
{  
    return strcasecmp($a["name"], $b["name"]);  
}  

usort($data, "cmp");  

var_dump($data);  
?>  

当我运行它时,它按预期工作,返回按名称排序的数据,升序。但是,我需要在课堂上使用它。

<?php
class myClass  
{  
    function getData()  
    {  
        // gets all data
        $this -> changeOrder($data);
    }  

    function changeOrder(&$data)  
    {  
         usort($data, "order_new");
    }

    function order_new($a, $b)  
    {  
        return strcasecmp($a["name"], $b["name"]);  
    }
}
?>

当我使用它时,我收到以下警告:警告:usort() 期望参数 2 是有效的回调,未找到函数 'order_new' 或无效的函数名称。

当我将 order_new 函数放在 changeOrder 函数中时,它工作正常,但是我遇到了致命错误的问题:无法重新声明 order_new(),所以我不能使用它。有什么建议么?

4

6 回答 6

113

order_new 是类方法而不是全局函数。正如PHP 手册所建议的那样,您可以在这种情况下使用

usort($data, array($this, "order_new")); 

或声明 order_new 静态并使用

usort($data, array("myClass", "order_new")); 
于 2012-07-03T14:27:39.737 回答
9

改成usort($data, array($this, "order_new"));

于 2012-07-03T14:25:30.560 回答
5
 usort($data, array($this,"order_new"));

是您在引用类实例中的函数时想要的。见可调用

实例化对象的方法作为数组传递,该数组包含索引 0 处的对象和索引 1 处的方法名称。

于 2012-07-03T14:25:44.790 回答
4

要考虑的一件事是,如果通过引用将变量传递给您的方法,则 usort() 似乎在引用变量的上下文中执行,而不是在您当前的方法中执行。因此,您需要在类引用中提供完整的命名空间,如下所示:

usort($data, ['My\NameSpace\MyClass', 'order_new']); 
于 2016-09-19T01:16:55.867 回答
1

我知道这是一个旧线程,但我今天遇到了另一个可能受益于另一种方法的实例。我有一个案例,我想使用一个特定的键,这样我就可以抽象出实际的支持功能。这导致使用包装函数找到一个版本,以返回一个匿名函数,该函数利用“使用”命令字提供用于在我的类中排序的键的名称。(在我的情况下,它是 [nested] 类的属性中的一个键,该键被分配给我正在进行排序的类属性之一 - 即我正在根据“维度”实例中的属性对实例进行排序分配给“项目”的属性,并希望能够按宽度、高度、长度或重量对它们进行排序)。然后获取回调函数,

/**
 * list of items
 *
 * @var Item[]
 */
public $items;

/**
 * @param string $key
 * @return \Closure
 */
private static function keySort($key) {
    return function ($ia, $ib) use ($key) {
        if($ia->dimensions->$key == $ib->dimensions->$key) return 0;
        return ($ia->dimensions->$key < $ib->dimensions->$key) ? -1 : 1;
    };
}

/**
 * return the list of items in the items array sorted by the value
 *   of the property specified by $key
 *
 * @param string $key
 * @return Item[]
 * @throws \Exception
 */
public function sortItemsByKey($key)
{
    if(in_array($key, array( 'width', 'length', 'height', 'weight', ))) {
        return usort($this->items, static::keySort($key));
    } else
        throw new \Exception(__METHOD__ . ' invalid sort key!');
}

这允许我使用 static:: 或 self:: 将其称为本地(可以想象,在这种情况下,我什至可以将其包装为非静态函数,因为我唯一担心的是得到调用但函数返回)我很快发现的另一个好处是我的尺寸对象还具有一些“计算”字段,例如周长、体积和体积重量。但一个问题是,尺寸重量取决于您是在国内还是国际运输物品,所以我需要告诉我的“calculateDimensionalWeight”函数它是否应该使用国际运输的价值。好吧,使用这种方法,我可以通过将附加参数传递给包装函数并将附加参数添加到使用变量来做到这一点。

/**
 * @param string $key
 * @param bool $intl // only used for dimensional weight
 * @return \Closure
 */
private static function keySort($key,$intl=false) {
    return function ($ia, $ib) use ($key,$intl) {
        switch($key) {
            case 'girth':
                $ia->dimensions->calculateGirth();
                $ib->dimensions->calculateGirth();
                break;
            case 'dimweight':
                $ia->dimensions->calculateDimensionalWeight($intl);
                $ib->dimensions->calculateDimensionalWeight($intl);
                break;
            case 'volume':
                $ia->dimensions->calculateVolume();
                $ib->dimensions->calculateVolume();
                break;
        }
        if($ia->dimensions->$key == $ib->dimensions->$key) return 0;
        return ($ia->dimensions->$key < $ib->dimensions->$key) ? -1 : 1;
    };
}

/**
 * return the list of items in the items array sorted by the value
 *
 * @param string $key
 * @param bool $intl  (only used for dimensional weight sorts on international shipments)
 * @return Item[]
 * @throws \Exception
 */
public function sortItemsByKey($key,$intl=false)
{
    if(in_array($key, array('value','collect', 'width', 'length', 'height', 'weight', 'girth', 'dimweight', 'volume'))) {
        return usort($this->items, static::keySort($key,$intl));
    } else
        throw new \Exception(__METHOD__ . ' invalid sort key!');
}

注意:以这种方式计算值会产生开销,因为任何列表中除了第一个和最后一个项目之外的所有项目在技术上都将被计算两次,这是多余的,但在这种情况下,我的列表并不长,在某些情况下,我需要在做的时候比较两个项目bin-sorting,所以它仍然是可取的。对于大型数据集,预先计算排序方法外部的值可能更明智。

于 2017-06-19T18:33:37.193 回答
0
// If order_new is a NORMAL function 
usort($data, [$this, 'order_new']);      // self ref object, function name  

// If order_new is a STATIC function 
usort($data, [__CLASS__, 'order_new']);  // string, function name 
于 2017-05-11T19:51:56.363 回答