Функция сортировки в «usort» «уклоняется» от PHP? Неустранимая ошибка: невозможно переопределить функцию? - PullRequest
2 голосов
/ 10 мая 2011

Недавно наткнулся на эту аккуратную небольшую ошибку или 'функцию' в PHP:

function myCmpFunc($a,$b) {
    function inner($p) {
         // do something
    }
    $inner_a = inner($a);
    $inner_b = inner($b);
    if ($inner_a == $inner_b) return 0;
    return ($inner_a > $inner_b ? -1 : 1);
}

В результате фатальная ошибка"не может переопределить функцию внутри в ...", когда вызывается так

usort($myArray, 'myCmpFunc');

Работает безупречно, когда функция inner объявлена ​​вне myCmpFunc и / или $ myArray содержит не более 2 элементов;)

- редактировать -

как-то Неустранимая ошибка PHP: невозможно переопределить функцию

Итак, вот мой вопрос: Можно ли объявить функции в локальной области видимости?

- редактировать 2 -

Возможно, это хорошо работает в PHP 5.3, просто прочитайте, что у него есть замыкания, даааа!

Ответы [ 4 ]

2 голосов
/ 10 мая 2011

function inner($p) определяется каждый раз, когда выполняется function myCmpFunc($a,$b).Кроме того, внутренняя функция видна снаружи function myCmpFunc($a,$b) после этого (что в значительной степени лишает смысла позволять определения вложенных функций).Вот почему вы получаете ошибку определения дубликата при повторном вызове внешней функции.

Чтобы обойти это, проверьте, есть ли function_exists в теле function myCmpFunc($a,$b).

1 голос
/ 13 июня 2013

Начиная с PHP v5.3, можно написать это следующим образом:

$myCmpFunc = function ($a, $b) {
    static $inner = function ($element) {
         return $element['width']; // just as an example
    };
    $inner_a = $inner($a);
    $inner_b = $inner($b);
    if ($inner_a == $inner_b) return 0;
    return ($inner_a > $inner_b ? -1 : 1);
};
usort($anArray, $myCmpFunc);
1 голос
/ 10 мая 2011

Проблема в том, что вы должны вызывать внешнюю функцию перед использованием внутренней функции.Согласно этому ответу на аналогичный вопрос Могу ли я включить функцию внутри другой функции?

Таким образом, использование inner($a); недопустимо.

1 голос
/ 10 мая 2011

Объявление функции находится внутри myCmpFunc, и поскольку usort будет вызывать myCmpFunc для каждого элемента массива, то, что происходит, аналогично объявлению функции N раз.

...