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_newstaticを宣言して、

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

考慮すべきことの1つは、変数が参照によってメソッドに渡された場合、usort()は、現在のメソッドではなく、参照された変数のコンテキストで実行されているように見えることです。したがって、次のようにクラス参照に完全な名前空間を指定する必要があります。

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

これが古いスレッドであることは知っていますが、今日、別のアプローチの恩恵を受ける可能性のある別のインスタンスに遭遇しました。実際のサポート機能を抽象化できるように、特定のキーを使用したい場合がありました。これにより、ラッパー関数を使用してバージョンを検索し、「use」コマンドワードを使用して無名関数を返し、クラスでの並べ替えに使用されるキーの名前を指定しました。(私の場合、これは、並べ替えを行っているクラスプロパティの1つに割り当てられている[ネストされた]クラスのプロパティのキーです。つまり、'dimensions'インスタンスのプロパティに基づいてインスタンスを並べ替えています。 '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::のいずれかを使用してローカルで呼び出すことができます(この場合、心配しているのは呼び出しを取得することだけですが、関数が返されるため、非静的関数としてラップすることもできます)私がすぐに発見したもう1つの利点は、寸法オブジェクトにも、周囲長、体積、寸法重量などの「計算された」フィールドがあることです。ただし、問題の1つは、商品を国内または海外に配送するかどうかによって寸法重量が異なるため、「calculateDimensionalWeight」関数に国際配送の値を使用するかどうかを指定する必要があることです。このメソッドを使用すると、ラッパー関数に追加のパラメーターを渡し、use変数に追加のパラメーターを追加するだけでそれを行うことができます。

/**
 * @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!');
}

注:この方法で値を計算すると、リストの最初と最後の項目を除くすべてが技術的に2回計算されるため、オーバーヘッドが発生します。これは冗長ですが、この場合、リストは長くなく、場合によっては、2つの項目を比較する必要があります。ビンソートなので、それでも望ましいです。大規模なデータセットの場合、sortメソッドの外部で値を事前に計算する方がおそらく賢明です。

于 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 に答える