Я пытаюсь преобразовать код PHP 5.3 в PHP 5.2 (который не поддерживает анонимные функции). Это код PHP 5.3:
$nr = 2; $a = array(1,2,3,4,5,6,7,8,9,10); $a = array_filter($a,function($e) use($nr) { return $e % $nr == 0; });
Мое преобразование таково:
array_filter($a,create_function('$e','return $e % $nr == 0;'));
Где следует use($nr)
?
global
будет работать нормально:
<?php $nr = 2; $a = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); $a = array_filter($a, create_function('$e', ' global $nr; return $e % $nr == 0; ')); var_dump($a);
Это эффективно дает нам доступ к «JavaScript-стилю», когда имеется только одна копия переменной, и любые записи, сделанные в эту переменную, будут видны везде:
<script> // javascript code: var a = 1; (function(){ a = 2; })(); console.log(a); // javascript shows 2 </script>
Однако обратите внимание, что функциональность, обеспечиваемая доступом «стиль JavaScript», отличается от use
, поскольку use
копирует значения, когда функция определена . Это означает, что с помощью use
имеется несколько копий переменных, а изменение одного не повлияет на другое:
<?php $a = 1; call_user_func(function()use($a){ $a = 2; }); var_dump($a); // php shows 1
Чтобы достичь этой функциональности (чтобы мы могли сделать «идеальную прокладку»), вы должны убедиться, что глобальные переменные не присваивают новые значения. Если вам нужно назначить новые значения для переменных,
Если вам нужно изменить исходное значение, вы можете сначала создать его копию, а затем глобализовать эту копию. Таким образом, ваше исходное значение не ограничено и может быть изменено:
<?php $nr = 2; $nr_copy = 2; $a = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); $nr = 3; // you can freely modify $nr because the function below is using $nr_copy $a = array_filter($a, create_function('$e', ' global $nr_copy; return $e % $nr_copy == 0; ')); var_dump($a);
Обратите внимание, что параметр 1 ( global
) не работает, если переменная, к которой вам нужно обратиться, находится в пределах области функции:
<?php some_function(); function some_function(){ $nr = 2; $a = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); $a = array_filter($a, create_function('$e', ' global $nr; // this will not work because $nr is undefined return $e % $nr == 0; ')); var_dump($a); }
Для таких случаев у вас нет выбора, кроме как использовать вариант 2.
Вы можете наложить значение непосредственно в определение функции:
<?php some_function(); function some_function(){ $nr = 2; $a = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); $a = array_filter($a, create_function('$e', ' return $e % '.$nr.' == 0; ')); var_dump($a); }
В случаях, когда простая конкатенация не работает (например, для массивов и объектов), единственным вариантом является сериализация:
<?php some_function(); function some_function(){ $nr = 2; $a = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); $a = array_filter($a, create_function('$e', ' return $e % unserialize(\''.str_replace("'", "\'", serialize($nr)).'\') == 0; ')); var_dump($a); }
Идея состоит в том, чтобы просто преобразовать переменную в строку, которую вы можете вставить в тело функции.
PHP 5.2 не поддерживает Closures. Следовательно, вы не можете использовать ключевое слово use
.
Если вам нужно, чтобы ваш код был совместимым с 5.2, вам было бы лучше просто создать именованную функцию / метод и передать необходимые параметры, а использовать create_function
поскольку последний может вызвать утечку памяти (каждая функция создается каждый раз, а gc не поймать их всех).
Вы можете использовать global
:
create_function('$e','global $nr; return $e % $nr == 0;')
Однако вам действительно нужно обновлять PHP, не беспокоясь о понижении: p
Вы можете использовать serialize / unserialize, как в:
create_function('$e','return $e % unserialize(\''.serialize($nr).'\') == 0;')