web-dev-qa-db-fra.com

Passer des paramètres supplémentaires pour usorter le rappel

J'ai les fonctions suivantes. WordPress fonctions, mais c'est vraiment une question PHP. Ils trient mes $term objets selon artist_lastname propriété dans les métadonnées de chaque objet.

Je veux passer une chaîne dans $meta dans la première fonction. Cela me permettrait de réutiliser ce code car je pouvais l'appliquer à diverses propriétés de métadonnées.

Mais je ne comprends pas comment je peux passer les paramètres extra au rappel usort. J'ai essayé de créer une fonction anonyme de style JS mais la version PHP sur le serveur est trop ancienne et a généré une erreur de syntaxe.

Toute aide - ou poussée vers le coin droit du manuel - est grandement appréciée. Merci!

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

En PHP, une option pour un rappel est de passer un tableau à deux éléments contenant un descripteur d'objet et un nom de méthode pour appeler l'objet. Par exemple, si $obj Était une instance de la classe MyCallable et que vous souhaitez appeler la méthode method1 De MyCallable sur $obj, alors vous pouvez passer array($obj, "method1") comme rappel.

Une solution utilisant ce type de rappel pris en charge consiste à définir une classe à usage unique qui agit essentiellement comme un type de fermeture:

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

Je pense que cette question mérite une mise à jour. Je sais que la question d'origine était pour PHP version 5.2, mais je suis venu ici à la recherche d'une solution et en ai trouvé une pour les versions plus récentes de PHP et j'ai pensé que cela pourrait être utile pour d'autres personnes également.

Pour PHP 5.3 et plus, vous pouvez utiliser le mot-clé 'se' pour introduire des variables locales dans la portée locale d'une fonction anonyme. Donc, ce qui suit devrait fonctionner:

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

Un code plus général

Si vous souhaitez trier un tableau une seule fois et avez besoin d'un argument supplémentaire, vous pouvez utiliser une fonction anonyme comme celle-ci:

usort($arrayToSort, function($a, $b) use ($myExtraArgument) {
    //$myExtraArgument is available in this scope
    //perform sorting, return -1, 0, 1
    return strcmp($a, $b);
});

Si vous avez besoin d'une fonction réutilisable pour trier un tableau qui a besoin d'un argument supplémentaire, vous pouvez toujours envelopper la fonction anonyme, comme pour la question d'origine:

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

En supposant que vous ayez accès aux objets et statiques (PHP 5 ou supérieur), vous pouvez créer un objet et passer les arguments directement là-bas, comme ceci:

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

En supposant que vous n'avez pas accès aux objets/statiques; vous pourriez juste faire un global:

$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

Avertissement Cette fonction est obsolète depuis PHP 7.2.0. Le recours à cette fonction est fortement déconseillé.

Les docs disent que create_function() devrait fonctionner sur PHP> = 4.0.1. Est-ce que cela fonctionne?

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

Cela ne vous aidera pas du tout avec usort() mais pourrait néanmoins être utile. Vous pouvez trier le tableau à l'aide de l'une des autres fonctions de tri, array_multisort() .

L'idée est de construire un tableau des valeurs sur lesquelles vous trieriez (les valeurs de retour de get_term_meta()) et de les trier en fonction de votre tableau principal $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