Использование обратного вызова в implode()
У меня есть многомерный массив, например:
$values = array(
'one' => array(
'title' => 'Title One',
'uri' => 'http://example.com/one',
),
'two' => array(
'title' => 'Title Two',
'uri' => 'http://example.com/two',
),
);
... и я хотел бы проанализировать это с закрытием в моей функции implode
, à la:
$final_string = implode(' | ', function($values) {
$return = array();
foreach($values as $value)
$return[] = '<a href="' . $value['uri'] . '">' . $value['title'] . '</a>';
return $return;
});
Однако это использование приводит к ошибке Invalid arguments passed
. Есть ли синтаксис, который мне не хватает, что сделает возможным использование закрытия? Я использую PHP v5.3.16.
Ответы
Ответ 1
Ответ Ashwin правильный. Здесь почему:
Когда вы передаете закрытие непосредственно методу implode
, который явно хочет второй аргумент типа array
, он, по существу, проверяет instanceof
- следовательно, неверный аргумент. Функция implode
не ожидает mixed
и не знает, чтобы выполнить закрытие.
Когда вы сначала назначаете эту функцию переменной, она заставляет PHP сначала оценивать эту переменную, и она заканчивает передачу возвращаемого значения из функции в implode
.
В этом случае вы возвращаете массив из функции и передаете это в implode
-, который проверяет.
изменить/добавить: эта анонимная функция будет instanceof Closure
.
Closure !== array
Ответ 2
Используйте 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
. После того, как мы изменили элементы в массиве, мы можем присоединиться к результатам.
Ответ 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;
Я не уверен, в чем причина, и вам нужно будет проверить это немного глубже, чтобы у вас была правильная причина.
Вы можете увидеть код, работающий здесь
EDIT. Преобразовал этот ответ в вики сообщества, чтобы каждый мог внести свой вклад.
РЕДАКТИРОВАТЬ: Объяснение @kmfk
Когда вы передаете закрытие непосредственно методу implode
, который явно хочет второй аргумент типа array
, он по существу проверяет instanceof
- следовательно, недопустимый аргумент. Функция implode
не ожидает типа mixed
и не знает, чтобы выполнить закрытие, чтобы получить array
.
Когда вы сначала назначаете эту функцию переменной, она заставляет PHP сначала оценивать эту переменную, и она заканчивает передачу возвращаемого значения из функции в implode
.
В этом случае вы возвращаете массив из функции и передаете это в implode
-, который проверяет.
Эта анонимная функция будет instanceof Closure
, а
Closure !== array
Ответ 4
Вы не можете использовать implode для того, что вы пытаетесь достичь, потому что implode принимает только 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);