13

I have a multidimensional array, e.g.:

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

...and I'd like to parse through that with a closure in my implode function, à la:

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

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

    return $return;
});

However, this usage yields an Invalid arguments passed error. Is there syntax that I'm missing which will make this use of closures possible? I'm using PHP v5.3.16.

4

5 回答 5

27

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

于 2013-06-26T03:51:35.963 回答
5

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

$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;

不过,我不确定原因是什么,并且需要更深入地检查它才能给你一个适当的理由。

您可以在此处查看代码

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

编辑:@kmfk 的解释

当您将闭包直接传递给implode方法时 - 它明确需要 type 的第二个参数array,它本质上会检查instanceof- 因此是无效参数。该implode函数不期望mixed类型,也不知道执行闭包以获得array.

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

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

该匿名函数将是instanceof Closure, 和

Closure !== array
于 2013-06-26T03:43:38.103 回答
2

阿什温的回答是正确的。 原因如下:

当您将闭包直接传递给implode方法时 - 它明确需要 type 的第二个参数array,它本质上会检查instanceof- 因此是无效参数。该implode函数不期望mixed也不知道要执行闭包。

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

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

编辑/添加:该匿名函数将是instanceof Closure.

Closure !== array
于 2013-06-26T03:49:58.473 回答
0

您不能使用 implode 来实现您想要实现的目标,因为 implode 只接受 anarray作为第二个参数。

你可以尝试这样的事情。

$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);
于 2013-06-26T03:43:40.037 回答
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>"; } );

查看示例代码

于 2018-05-04T10:49:49.633 回答