上面定义的回调函数未找到

时间:2016-05-21 13:42:10

标签: php arrays callback

我有这个代码片段,可以找到两个Feed数组之间的差异:

protected function execute()
{
    $existingFeedItems = $feed->getItems();
    $newFeedItems = $feed->loadItems();

    function compareFeedItemIds($feedItem1, $feedItem2)
    {
        return $feedItem1->getFeedItemId() == $feedItem2->getFeedItemId() ? 0 : -1;
    }

    $feedItemsAdded = array_udiff($newFeedItems, $existingFeedItems, "compareFeedItemIds");
    $feedItemsRemoved = array_udiff($existingFeedItems, $newFeedItems, "compareFeedItemIds");
    $unchangedFeedItems = array_uintersect($newFeedItems, $existingFeedItems, "compareFeedItemIds");
}

这会抛出错误:

  

警告:array_udiff()期望参数3是有效的回调,   函数'compareFeedItemIds'未找到或函数名称无效

即使我已经定义了上述功能。 PHP抛出此错误的原因是什么?我必须添加我从对象的方法上下文执行它。

2 个答案:

答案 0 :(得分:2)

如果您的回调函数是在命名空间中定义的,那么您需要在进行udiff()调用时指明该命名空间。

$feedItemsAdded = array_udiff($newFeedItems, $existingFeedItems, "namespace\\compareFeedItemIds");

否则PHP将在全局命名空间

中搜索回调函数

答案 1 :(得分:2)

让我们假设拥有一个本地函数定义和/或lambda函数确实是一个好主意(如果你有相同的函数定义分散在你的项目上,它会变得不那么有吸引力。 ...)。
可以在另一个函数/方法中定义一个函数,这个定义只在脚本执行到达这个代码时才会发生。但是:功能定义不是本地的;它起泡 - 在函数/类之外。因此,你将得到一个"无法重新声明函数compareFeedItemIds"如果您多次执行execute(),则会出错 有几个选项来修复"这一点。
您可以将函数分配给局部变量,然后将该变量作为第三个参数传递给array_ *函数。

$compareFeedItemIds = function($feedItem1, $feedItem2) {
    return $feedItem1->getFeedItemId() == $feedItem2->getFeedItemId() ? 0 : -1;
};

$feedItemsAdded = array_udiff($newFeedItems, $existingFeedItems, $compareFeedItemIds);
$feedItemsRemoved = array_diff($existingFeedItems, $newFeedItems, $compareFeedItemIds);
....

您还可以将该函数存储在实例变量...或静态类成员中。

或者......为了避免namspace问题,只需在类中创建一个静态方法,然后通过self :: methodname或static::methodname引用该方法,例如。

<?php
class Foo {
    public function bar() {
        $a = [1,2,3];
        $b = [2,3,4];

         var_export( array_udiff($a, $b, 'self::moo') );
         var_export( array_udiff($b, $a, 'self::moo') );
         var_export( array_uintersect($a, $b, 'self::moo') );
    }

    protected static function moo($a,$b) {
        return $a<=>$b;
    }
}

$foo = new Foo;
$foo->bar();