2013-06-26 4 views
10

У меня есть многомерный массив, например:Использование обратного вызова в Implode()

$values = array(
    'one' => array(
     'title' => 'Title One', 
     'uri' => 'http://example.com/one', 
    ), 
    'two' => array(
     'title' => 'Title Two', 
     'uri' => 'http://example.com/two', 
    ), 
); 

... и я хотел бы разобрать через что с закрытием в моей implode функции, а-ля:

$final_string = implode(' | ', function($values) { 
    $return = array(); 

    foreach($values as $value) 
     $return[] = '<a href="' . $value['uri'] . '">' . $value['title'] . '</a>'; 

    return $return; 
}); 

Однако это использование дает ошибку Invalid arguments passed. Есть ли синтаксис, который мне не хватает, что может сделать это использование closures возможным? Я использую PHP v5.3.16.

+1

Согласно документам 'implode' не принимает обратный вызов ... Или я что-то не хватает? Если вы просто хотите сгенерировать массив с помощью функции и использовать ее как параметр, вам нужно будет выполнить функцию с помощью 'call_user_func'. – elclanrs

+0

$ return = array(); foreach ($ values ​​as $ value) $ return [] = ' ccd580ac6753941c6f84fe2e19f229

+0

Спасибо @elclanrs - Возможно, я ошибаюсь в закрытии, но я так не думаю. Анонимная функция, которую я определил в вопросе _does_, возвращает массив, удовлетворяющий требованию 'implode'. Am _I_ отсутствует что-то? :) – jterry

ответ

2

Ответ Эшвина верен. Вот почему:

Когда вы передаете замыкание непосредственно к implode метод - который явно хочет второй аргумент типа array, он по существу проверяет instanceof - отсюда неверный аргумент. Функция implode не ожидает mixed и не знает, чтобы выполнить закрытие.

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

В этом случае вы возвращаете массив из функции и передаете это в implode - это проверяет.

изменить/добавить: эта анонимная функция будет instanceof Closure.

Closure !== array 
+0

Урок выучен ... спасибо @kmfk. Простое доказательство того, что вы совершенно правы: 'is_array (function() {return array();});' возвращает 'false'. – jterry

+1

Боковое примечание, спасибо, что ответили на фактический ** вопрос ** - не только для решения _some_ :) – jterry

3

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

$fn = function($values) { 
    $return = array(); 
    foreach($values as $value) 
     $return[] = '<a href="' . $value['uri'] . '">' . $value['title'] . '</a>'; 
    return $return; 
}; 
$final_string(' | ', $fn($values)); 
echo $final_string; 

Я не уверен, что причина, хотя и нужно будет проверить его в немного больше глубины, чтобы быть в состоянии дать вам правильную причину.

Вы можете увидеть код рабочего here

EDIT: конвертировано этот ответ сообщества вики, так что каждый может внести свой вклад здесь.

EDIT: Разъяснение @kmfk

Когда вы передаете замыкание непосредственно к implode метод - который явно хочет второй аргумент типа array, он по существу проверяет instanceof - отсюда неверный аргумент. Функция implode не ожидает mixed и не знает, чтобы выполнить закрытие, чтобы получить array.

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

В этом случае вы возвращаете массив из функции и передаете это в implode - это проверяет.

Это анонимная функция будет instanceof Closure и

Closure !== array 
+0

Спасибо @Ashwin Mukhija - хотел бы знать, почему нам нужно пройти этот дополнительный шаг, чтобы выполнить _essentially_ то же самое. – jterry

+0

объяснено в моем ответе [здесь] (http://stackoverflow.com/a/17311224/396318) – kmfk

+0

Потому что вы можете ' t просто отбросьте все, что вам нравится, на собственные PHP-функции. Они должны использоваться как разработанные и задокументированные. –

0

Вы не можете использовать лопаются к тому, что вы пытаетесь достичь, потому что взрываются только принять array в качестве второго аргумента.

Вы можете попробовать что-то вроде этого.

$values = array(
    'one' => array(
     'title' => 'Title One', 
     'uri' => 'http://example.com/one', 
    ), 
    'two' => array(
     'title' => 'Title Two', 
     'uri' => 'http://example.com/two', 
    ), 
); 

$links = array(); 
foreach ($values as $value) { 
     $links[] = "<a href='" . $value['uri'] . "'>" . $value['title'] . "</a>"; 
} 

$string = implode(" | ", $links); 
16

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

$final_string = implode(' | ', array_map(function($item) { 
    return '<a href="' . $item['uri'] . '">' . $item['title'] . '</a>'; 
}, $values)); 

Я надеюсь, что вы будете правильно избежать значения, как HTML в вашем реального кода.


Как, почему это работает, и ваш код не вы проезжали функцию в качестве второго аргумента implode. Честно говоря, это мало смысла: вы можете объединить кучу строк или, может быть, даже кучу функций, но вы не можете присоединиться к одной функции вместе. Это звучит странно, особенно если вы так говорите.

Вместо этого мы сначала хотим преобразовать все элементы в массиве с помощью функции и передать результат , что в implode. Эта операция обычно называется map. К счастью, PHP предоставляет эту функцию, как, ну, array_map. После того, как мы изменили элементы в массиве, мы можем присоединиться к результатам.

+0

Удалил мой ответ, это просто чище. Нет необходимости в дополнительном закрытии. – elclanrs