web-dev-qa-db-ja.com

usortコールバックに追加のパラメーターを渡す

以下の機能があります。 WordPress関数ですが、これは実際にはPHP質問です。各オブジェクトの$termプロパティに従ってartist_lastnameオブジェクトを並べ替えますメタデータ。

最初の関数の$metaに文字列を渡したいのですが。これにより、さまざまなメタデータプロパティに適用できるため、このコードを再利用できます。

しかし、私はextraパラメータを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); 
} 
38
djb

PHPでは、 callback の1つのオプションは、オブジェクトハンドルとオブジェクトで呼び出すメソッド名を含む2要素の配列を渡すことです。たとえば、$objがクラスMyCallableのインスタンスであり、method1MyCallable$objメソッドを呼び出す場合、array($obj, "method1")をコールバックとして渡すことができます。

このサポートされているコールバックタイプを使用する1つのソリューションは、基本的にクロージャタイプのように機能する使い捨てクラスを定義することです。

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);
    }
}
23
Daniel Trebbien

この質問は更新に値すると思います。私は元の質問がPHPバージョン5.2に関するものであったことを知っていますが、解決策を探してここに来て、PHPの新しいバージョンのための1つを見つけました。他の人にも役立ちます。

PHP 5.3以降では、 'se'キーワードを使用して、ローカル変数を無名関数のローカルスコープに導入できます。したがって、以下が機能するはずです。

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

より一般的なコード

配列を1回だけ並べ替えて、追加の引数が必要な場合は、次のような無名関数を使用できます。

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

オブジェクトと静的(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'));

オブジェクト/静的にアクセスできないと仮定します。あなたは単にグローバルにすることができます:

$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');
7
Kato

警告この関数はPHP 7.2.0。の時点で廃止されました。この関数に依存することは強くお勧めしません。

ドキュメントは 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");'));
3
John Watson

これはusort()ではまったく役に立ちませんが、それでも役立つ場合があります。他のソート関数 array_multisort() を使用して配列をソートできます。

ソートする値の配列(get_term_meta()からの戻り値)を作成し、メインの$terms配列に対してマルチソートするという考え方です。

function sort_by_term_meta(&$terms, $meta) 
{
    $sort_on = array();
    foreach ($terms as $term) {
        $sort_on[] = get_term_meta($term->term_id, $meta, true);
    }
    array_multisort($sort_on, SORT_ASC, SORT_STRING, $terms);
}
1
salathe