Попытка понять странный вариант вызова PHP array_map () - PullRequest
2 голосов
/ 20 апреля 2011

Я пытаюсь понять некоторый код, который я нашел в библиотеке oauth-php с открытым исходным кодом. Соответствующий фрагмент кода:

protected function sql_printf ( $args )
{
    $sql  = array_shift($args);
    if (count($args) == 1 && is_array($args[0]))
    {
        $args = $args[0];
    }
    $args = array_map(array($this, 'sql_escape_string'), $args);
    return vsprintf($sql, $args);
}

Где $ args - это массив аргументов, которые содержат переменные, предназначенные для использования в операции форматированной печати. Я посмотрел на документы для array_map:

http://php.net/manual/en/function.array-map.php

и пользователь комментирует, и я не видел ни одного варианта использования, где первым параметром в вызове array_map () был сам массив. Во всех случаях использования, которые я видел, первым параметром была либо NULL, либо функция (обратного вызова). Мне кажется довольно очевидным, что код берет массив $ args и затем строит новый массив с аргументами, очищенными с помощью $ this-> sql_escape_string ().

Но утверждение «массив ($ this, 'sql_escape_string')» меня выбрасывает, поскольку я ожидал бы просто «$ this-> sql_escape_string», или это неверный синтаксис? Если это так, как перенос $ this и 'sql_escape_string' в массив создает действительную функцию обратного вызова для использования array_map ()?

- Рошлер

Ответы [ 3 ]

3 голосов
/ 20 апреля 2011

Первый параметр - это обратный вызов . Это может быть либо строка, либо массив.

так как я ожидал бы просто '$ this-> sql_escape_string'

Вы бы, если бы это было только одно скалярное значение. Но у вас есть массив, и вам нужно применить эту escape-функцию к каждому элементу массива $args. Таким образом, вам нужно реализовать foreach и применить эту функцию или использовать однострочное с array_map.

3 голосов
/ 20 апреля 2011

Он фактически передает метод sql_escape_string из самого класса в качестве обратного вызова. Это способ выяснения неоднозначных вызовов методов. Например:

array_map('sql_escape_string', $args);

конечно применяется sql_escape_string() к каждому значению в $args, тогда как:

array_map(array($someClass, 'sql_escape_string'), $args);

применяет метод sql_escape_string() из $someClass к каждому значению в $args.

1 голос
/ 05 августа 2013

Но утверждение "массив ($ this, 'sql_escape_string')" меня выбрасывает, поскольку я ожидал бы просто '$ this-> sql_escape_string' или это неверный синтаксис?

Это действительно, но не относится к тому, что вы думаете, это относится. Рассмотрим свободные функции, константы, имена классов и переменные: каждая существует в разных средах (или «пространствах имен», если вы предпочитаете, но это легко спутать с пространствами имен PHP ). Различная среда для переменных становится явной с помощью использования "$" в качестве сигил : переменная $foo против функции foo(), константа foo и класс Foo. Именно поэтому константы и переменные чувствительны к регистру, а имена функций и классов - нет: разные среды допускают разные правила разрешения имен.

Аналогично, методы и свойства объекта существуют в разных средах. Как следствие, $this->sql_escape_string относится к свойству, а не к методу. Чтобы запутать вещи, это свойство может содержать вызываемый объект, хотя такой вызываемый объект не может быть вызван напрямую :

class Foo {
    function frob() {return 23.0 / 42;}
}

$foo = new Foo;
$foo->frob = function () {return 0 / 0;};

$foo->frob(); # calls method, not closure function

$frob = $foo->frob;
$frob(); # oops: division by zero

Как и в случае констант и функций, свойства и методы отличаются отсутствием или наличием списка аргументов.

Если это так, как перенос $ this и 'sql_escape_string' в массив создает действительную функцию обратного вызова для использования array_map ()?

Синтаксис PHP для вызываемых ссылок выходит за рамки строк.

Свободные функции (функции, не связанные с классом или объектом; в отличие от «связанных функций») могут однозначно именоваться их именами. Статические методы связаны с классом, но на них можно ссылаться строкой, если она включает имя класса (синтаксис «Class :: method»). Однако строка не может содержать достаточно информации для метода объекта, поскольку метод должен быть привязан к определенному объекту, а PHP не имеет возможности ссылаться на объект с помощью строки. Решением, на котором остановились разработчики PHP, было использование синтаксиса массива (как показано в примере кода вопроса). Они также включили поддержку синтаксиса массива для статических методов (array('Class', 'method')).

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

$self = $this; # workaround: $this not accessible in closures before 5.4
$args = array_map(
    function ($value) use($self) {
        return $self->sql_escape_string($value);
    }, $args);

Замыкания не так полезны, когда подойдет вызываемая ссылка, но в целом более эффективны.

...