PHP изменить код, чтобы избежать анонимных функций

Я нашел некоторые решения проблемы сортировки, которые у меня были, но код использует анонимные функции в PHP. Im, использующий версию 5.2.17, и я считаю, что анонимные функции не поддерживаются.

Как я могу изменить следующие блоки кода, чтобы я мог использовать их в PHP 5.2.17

$keys = array_flip($order); usort($items, function($a, $b) use($keys) { return $keys[$a['id']] - $keys[$b['id']]; }); 

из многомерного массива сортировки PHP другим массивом

А также

 $sorted = array_map(function($v) use ($data) { return $data[$v - 1]; }, $order); 

от PHP – Сортировка многомерного массива другим массивом

ОБНОВЛЕНИЕ: Одна из проблем заключается в том, что я не уверен, как используются переменные $ a, $ b и $ v. Поэтому я не уверен, как создавать нормальные функции, минуя функции анона.

Обе анонимные функции use предложение use для передачи переменных в локальную область.

Вы можете добиться того же, что и объектные методы, в которых объекты имеют эти переменные как свойства.

Внутри метода объекта вы можете получить к ним доступ.

 $sorted = array_map(function($v) use ($data) { return $data[$v - 1]; }, $order); 

Примерный объект сопоставления мог бы выглядеть так:

 class MapObj { private $data; public function __construct($data) { $this->data = $data; } public function callback($v) { return $this->data[$v - 1]; } } 

Как вы можете видеть, он имеет ту же функциональность, но просто написан в синтаксисе PHP 5.2.

И это использование:

 $map = new MapObj($data); $callback = array($map, 'callback'); $sorted = array_map($callback, $order); 

И вот как это работает. Обратные вызовы для объектных методов всегда записываются в виде array с двумя членами, первый – экземпляр объекта, а второй – это имя метода объекта.

Естественно, вы можете расширить это, поместив функцию отображения в объект сопоставления, так что это более прямолинейно:

 class MapObj { ... public function map(array $order) { $callback = array($this, 'callback'); return array_map($callback, $order); } } 

Новое использование:

 $map = new MapObj($data); $sorted = $map->map($order); 

Как вы можете видеть, это может сделать использование немного более прямым. Должен признаться, мой метод имен не очень блестящий здесь, поэтому я оставляю место для ваших улучшений.

Другим преимуществом является то, что вы можете сделать видимость метода обратного вызова приватным.


Ситуация с передачей данных для работы в обратном вызове в качестве параметра функции сопоставления. Это потому, что вы написали, что у вас уже есть класс, который вы хотите использовать, но вы не можете коснуться конструктора. Таким образом, данный пример немного короток.

Вот еще один пример без использования конструктора, я удалил его:

 class MyObj { private $data; private function callback($v) { return $this->data[$v - 1]; } public function map($order, $data) { $callback = array($this, 'callback'); $this->data = $data; return array_map($callback, $order); } } 

Как вы можете видеть, конструктор больше не нужен для передачи $data , но вместо этого он просто передается в метод map() в качестве дополнительного параметра. Применение:

 $myObj = new MyObj(....); // somewhere. // later on: $myObj->map($order, $data); // could be also: $this->map($order, $data); 

Как вы можете видеть, как вы устанавливаете переменную частного члена, зависит от вас. Сделайте то, что подходит для работы.

Здесь у вас есть закрытие над $data – на 100% невозможно переписать его без анонимной функции. Вот ближайшая возможная аппроксимация:

 function _array_sort_callback($a, $b) { global $_array_sort_callback__keys; return $_array_sort_callback__keys[$a['id']] - $_array_sort_callback__keys[$b['id']]; } ... { $keys = array_flip($order); global $_array_sort_callback__keys; $_array_sort_callback__keys = $keys; usort($items, "_array_sort_callback"); } 

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

Кроме того, имейте в виду, что PHP 5.2.17 устарел и не поддерживается. Вы должны как можно скорее перейти от него.

Если вы хотите подражать закрытию, где вы моментальные снимки в определенное время, вы можете использовать простой базовый класс, чтобы служить контейнером для значений, а затем просто определить подклассы для реализации логики сравнения.

Непроверенные

 // base class exists purely to capture the value of some variables at instantiation time // kinda like a closure class VarCapture { protected $vars; function __construct($vars) { $this->vars = $vars; } } class ItemComparer extends VarCapture { function compare($a, $b) { $keys = $this->vars['keys']; return $keys[$a['id']] - $keys[$b['id']]; } } class PluckMapper extends VarCapture { function pluck($v) { $data = $this->vars['data']; return $data[$v - 1]; } } $keys = array_flip($order); $ic = new ItemComparer(compact('keys')); $callable = array($ic, 'compare'); usort($items, $callable); $pm = new PluckMapper(compact('data')); $callable = array($mp, 'pluck'); $sorted = array_map($callable, $order); 

Обратите внимание, что я использовал php callback psuedo type http://php.net/manual/en/language.types.callable.php

Вы также можете переписать его в анонимные функции до 5.3, a la create_function() . Хотя функции create_function() обычно не действуют как замыкания, вы можете использовать некоторые трюки (без использования глобальных переменных), чтобы заставить их работать как замыкания в некоторых ограниченных обстоятельствах. Вы кодируете закрытые переменные непосредственно в источник функции. Ограничения заключаются в том, что данные только идут в одну сторону; закрытые переменные могут быть только «простыми» типами данных, такими как числа, строки и массивы; и функции, созданные с помощью create_function , никогда не освобождаются, утечка памяти; плюс это не очень эффективно. Но я думаю, что этого достаточно для вашего примера (предполагая, что вы используете только массивы и строки и т. Д.).

 $keys = array_flip($order); usort($items, create_function('$a,$b', '$keys = '.var_export($keys,true).'; return $keys[$a["id"]] - $keys[$b["id"]]; ')); 

а также

 $sorted = array_map(create_function('$v', '$data = '.var_export($data,true).'; return $data[$v - 1]; '), $order); 

Тем не менее, более общее решение до 5.3 означает использование объекта и метода в качестве закрытия, как в ответе хакры.