在一个类中的usort函数

我有一个multidimensional arraysorting数据的函数,如下所示:

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

当我运行这个,它按预期工作,返回按名称sorting的数据,升序。 不过,我需要在课堂上使用这个。

 <?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是一个有效的callback,找不到function'order_new'或无效的函数名称。

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

order_new是一个类方法而不是全局函数。 由于PHP手册build议您可以在这种情况下使用

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

或者声明order_new静态和使用

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

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

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

是你在你的类实例中引用一个函数时想要的。 看到callable

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

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

 usort($data, ['My\NameSpace\MyClass', 'order_new']); 
 // 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 

我知道这是一个古老的线索,但今天我遇到了另一个可能受益于另一种方法的例子。 我有一个情况,我想使用一个特定的键,所以我可以抽象出实际的支持function。 这导致find一个版本使用包装函数返回一个匿名函数利用'使用'命令字提供用于在我的课堂sorting的关键字名称。 (在我的情况下,这是一个[嵌套]类的属性中的一个关键分配给我正在做sorting的类属性之一 – 即我基于“维”实例中的属性sorting实例分配给“物品”的属性,并希望能够按照宽度,高度,长度或重量进行分类)。 然后为了获得你的callback函数,你只需要用你想用来sorting结果的密钥名来调用这个包装函数:

 /** * 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'函数是否应该使用国际航运的价值。 那么,使用这种方法,我可以通过传递一个额外的参数到包装函数,并添加额外的参数到使用variables。 由于我还需要确保在进行任何比较之前计算出这些值,所以我可以在基于密钥的函数中触发该值:

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