在课堂上使用函数

时间:2012-07-03 14:23:15

标签: php

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

<?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()的问题,所以我不能使用它。有什么建议吗?

6 个答案:

答案 0 :(得分:95)

order_new是一个类方法而不是全局函数。 正如PHP-Manual建议你可以在这种情况下使用

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

或声明order_new static并使用

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

答案 1 :(得分:9)

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

答案 2 :(得分:5)

 usort($data, array($this,"order_new"));
在您的类实例中引用函数时,

是您想要的。见callable

  

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

答案 3 :(得分:2)

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

usort($data, ['My\NameSpace\MyClass', 'order_new']); 

答案 4 :(得分:1)

我知道这是一个旧线程,但我今天遇到了另一个可能受益于另一种方法的实例。我有一个案例,我想使用特定的键,所以我可以抽象实际的支持功能。这导致找到一个使用包装函数返回匿名函数的版本,该函数使用'use'命令字来提供用于在我的类中排序的键的名称。 (在我的例子中,它是[嵌套]类的属性中的一个键,它被分配给我正在进行排序的类属性之一 - 即我根据'维'实例中的属性对实例进行排序分配给'items'的属性,并希望能够按宽度,高度,长度或重量对它们进行排序)。然后,为了获得回调函数,只需使用要用于对结果进行排序的键名称调用此包装函数:

/**
 * 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排序时的项目,所以它仍然是可取的。对于大型数据集,预先计算排序方法外部的值可能更明智。

答案 5 :(得分: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