У меня есть следующие функции. Функции Wordpress, но это действительно вопрос PHP. Они сортируют мои объекты $term
в соответствии с свойством artist_lastname
в каждом метаданных объекта.
Я хочу передать строку в $meta
в первой функции. Это позволит мне повторно использовать этот код, поскольку я могу применить его к различным свойствам метаданных.
Но я не понимаю, как я могу передать дополнительные параметры для обратного вызова 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);
}
В PHP один вариант для callback - передать двухэлементный массив, содержащий дескриптор объекта и имя метода для вызова на объект. Например, если $obj
был экземпляром класса MyCallable
, и вы хотите вызвать метод method1
MyCallable
на $obj
, то вы можете передать array($obj, "method1")
в качестве обратного вызова.
Одним из решений, использующих этот поддерживаемый тип обратного вызова, является определение одноразового класса, который по существу действует как тип замыкания:
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);
}
}
$meta
. PHP является однопоточным, так что это не прерыватель сделки. Тем не менее, я думаю, что лучше инкапсулировать строку $meta
чтобы код не мог случайно изменить содержимое статической переменной во время выполнения сортировки.
Я думаю, что этот вопрос заслуживает обновления. Я знаю, что исходный вопрос был для PHP версии 5.2, но я пришел искать решение и нашел его для более новых версий PHP и думал, что это может быть полезно и для других людей.
Для PHP 5.3 и выше вы можете использовать ключевое слово use, чтобы ввести локальные переменные в локальную область анонимной функции. Таким образом, следующее должно работать:
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);
});
}
Если вы хотите отсортировать массив только один раз и вам нужен дополнительный аргумент, вы можете использовать анонимную функцию следующим образом:
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);
});
}
Предполагая, что вы имеете доступ к объектам и статическим (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'));
Предполагая, что у вас нет доступа к объектам /static; вы могли бы просто сделать глобальный:
$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');
SortWithMeta::sort
я считаю, что параметр $terms
SortWithMeta::sort
должен передаваться по ссылке.
Документы говорят, что 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");'));
Это не поможет вам с 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);
}