在implode()中使用回调

时间:2013-06-26 03:35:05

标签: php closures

我有一个多维数组,例如:

$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错误。我是否缺少可以使用closures的语法?我正在使用PHP v5.3.16。

5 个答案:

答案 0 :(得分:19)

使用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。在我们转换了数组中的项目后,我们可以加入结果。

答案 1 :(得分:4)

似乎您需要将函数分配给变量,然后将其传递以使其工作。

$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

编辑:将此答案转换为社区维基,以便每个人都可以在这里做出贡献。

编辑:@kmfk解释

当你将闭包直接传递给implode方法 - 它明确地想要第二个类型为array的参数时,它实际上会检查instanceof - 因此无效的参数。 implode函数不期望mixed类型,并且不知道执行闭包以获得array

当您首次将该函数分配给变量时,它会导致PHP首先评估该变量,并最终将函数的返回值传递给implode

在这种情况下,您将从函数返回一个数组并将其传递给implode - 这将检出。

匿名函数为instanceof Closure

Closure !== array

答案 2 :(得分:2)

Ashwin的回答是正确的。 原因如下:

当你将闭包直接传递给implode方法 - 它明确地想要第二个类型为array的参数时,它实际上会检查instanceof - 因此无效的参数。 implode函数不期望mixed并且不知道执行闭包。

当您首次将该函数分配给变量时,它会导致PHP首先评估该变量,并最终将函数的返回值传递给implode

在这种情况下,您将从函数返回一个数组并将其传递给implode - 这将检出。

编辑/添加:匿名函数为instanceof Closure

Closure !== array

答案 3 :(得分:0)

你不能将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);

答案 4 :(得分:0)

function implode_callback( $array, $separator = '', $callback = false )
{
    return implode(
                    $separator,

                    $callback === false ?
                      $array : array_map( $callback, $array )
                  );
}

使用示例:

$tab = array( 1, 2, 3 );

echo implode_callback( $tab, '<hr>', function($x) { return "<p>$x</p>"; } );

See example code